Vue3中常用的语法详细分解(响应式数据,声明响应式数据,自定义事件,计算属性,监听器)

简介: Vue3中常用的语法详细分解(响应式数据,声明响应式数据,自定义事件,计算属性,监听器)

1. 创建Vue实例

Vue3使用API一律是函数式风格所以和new告别了。

// Vue3.0
import {createApp} from 'vue'
createApp(App).use(router).use(store).mount('#app')
// Vue2.0
import Vue from 'vue'
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

1.1 其他的区别

全局

// vue2
import Vue from 'vue'
Vue.component(...)
// vue3
import {createApp} from 'vue'
let app = createApp(App)
app.component(...)

filter 没有了

全局


Vue.component -> app.component

filter没了 filter -> computed/method

v-model value+input -> value+input || modelValue+update:modelValue

函数h render(h) -> import {h} from ‘vue’

data data: {} || data(){} -> data(){}

异步组件 ()=>import(’…’) -> defineAsyncComponent(()=>import(’…’))

事件 e m i t 、 emit、 emit、on、… -> $emit

其他 …

2. 响应式数据

模板定制

<template>
  <div class="hello" style="border:1px solid">
    <h1 ref="root">{{ msg }}</h1>
    {{state.count}} double is {{double}}
    <button @click="add">+</button>
  </div>
</template>

2.1 声明响应式数据

// Vue2
export default {
  // ....
  data() {
    return {
      state: {
        count: 0
      }
    };
  },
}
// Vue3 reactive 
export default {
  // ....
  setup(){
    const state = reactive({
      count:0
    })
    return {state}
  }
}

2.2 自定义事件

// Vue2
export default {
  // ....
  methods: {
    add() {
      this.state.count++;
    }
  },
}
// Vue3
export default {
  // ....
  setup(){
    const add = () => {
      state.count++
    }
    return {add}
  }
}

2.3 计算属性

// Vue2
export default {
  // ...
  computed: {
    double() {
      return this.state.count * 2;
    }
  },
}
// Vue3
export default {
  // ...
  setup(){
    const double = computed (() => state.count * 2 )
    return {double}
  }
}

2.4 监听器

// Vue2
export default {
  // ...
  watch: {
    count: value => {
      console.log("count is changed:", value);
    }
  }
}
// Vue3
export default {
  // ...
  setup(){
    watch(
      () => state.count,
      value => {
        console.log('state change :',value)
      }
    )
  }
}

2.5 生命周期及其获取Dom元素

// Vue2
<div ref="dom"></div>
export default {
  // ...
  mounted() {
    this.$refs.dom.style.color = "red";
  }
}
// Vue3
<h1 ref="myRef">7777777777777777777</h1>
export default {
  // ...
  setup() {
    // ref 创建一个响应式的数据对象
    const myRef = ref(null);
    onMounted(() => {
      console.dir(myRef);
       const dom = myRef.value
      dom.style.color = 'red'
    });
    return {
      myRef
    }
  },
}

3. API 列表

const {
  createApp,
  reactive, // 创建响应式数据对象
  ref, // 创建一个响应式的数据对象
  toRefs, // 将响应式数据对象转换为单一响应式对象
  isRef, // 判断某值是否是引用类型
  computed, // 创建计算属性
  watch, // 创建watch监听
  // 生命周期钩子
  onMounted,
  onUpdated,
  onUnmounted,
} = Vue

3.1 setup使用composition API的入口

setup函数会在 beforeCreate之后 created之前执行

setup(props,context){
    console.log('setup....',)
    console.log('props',props) // 组件参数
    console.log('context',context) // 上下文对象
} 

3.2 reactive

reactive() 函数接受一个普通对象 返回一个响应式数据对象

const state = reactive({
        count: 0,
        plusOne: computed(() => state.count + 1)
    })

3.3 ref 与 isRef

ref 将给定的值(确切的说是基本数据类型 ini 或 string)创建一个响应式的数据对象

isRef 其实就是判断一下是不是ref生成的响应式数据对象

 // 定义创建响应式数据
    const time = ref(new Date())
    // 设置定时器为了测试数据响应
    setInterval(() => time.value = new Date(), 1000)
    // 判断某值是否是响应式类型
    console.log('time is ref:', isRef(time))
    console.log('time', time)
    console.log('time.value', time.value)
    // 我们看看模板里面我们这样展示
    template: `
        <div>
            <div>Date is {{ time }}</div>
        </div>
    `

3.4 toRefs

toRefs就是ref的批量操作

toRefs 可以将reactive创建出的对象展开为基础类型

1.
// 如果不用toRefs
    const state = reactive({
        count: 0,
        plusOne: computed(() => state.count + 1)
    })
    return {
        state
    }
    // 模板渲染要这样写
    template: `
    <div>
        <div>count is {{ state.count }} </div>
        <div>plusOne is {{ state.plusOne }}</div>
    </div>
    `
    // 我们再看看用了toRefs
    const state = reactive({
        count: 0,
        plusOne: computed(() => state.count + 1)
    })
    return {
        ...toRefs(state)
    }
    // 模板渲染要这样写
    template: `
    <div>
        <div>count is {{ count }} </div>
        <div>plusOne is {{ plusOne }}</div>
    </div>
    `

3.5 watch 定义监听器

这个其实没有什么新东西,需要手动指定

watch(() => 谁,()=>{})
watch(() =>[a,b....], ()=>{})
watch(() => state.count * 2, val => {
        console.log(`count * 2 is ${val}`)
 })

3.5.1 watchEffect 自动监听

自动监听,当watchEffect内部使用了某个值会自动监听这个值变化,当这个值变化的时候触发

 watchEffect((invalidate) => { 
  console.log('a变了',a)     
 })
invalidate: 参数是一个函数,放监听器失效的时候触发。监听器什么时候会失效?stop的时候、或者组件销毁
invalidate(()=>{})

3.5.2 停止监听

 let stop = watchEffect((invalidate) => {})
 let stop1 = watch(() => 谁,()=>{})
 stop()
 stop1()

3.6 ffect 副作用函数

响应式对象修改会触发这个函数

    // 副作用函数
    effect(() => {
        console.log('数值被修改了..',state.count)
    })

3.7 computed 计算属性

const state = reactive({
    count: 0,
    plusOne: computed(() => state.count + 1)
})

3.8 provide/inject 依赖注入

// 外部组件
setup(){ 
  provide(名字,值【可以是任何类型】)  
}
// 内部
setup(){ 
  const a = inject(名字,可选参:默认值)

toRaw 与 markRaw

toRaw 拿出reactive、ref、readonly这个方法转换前的原始互数据,对原始数据操作不会被监听

markRaw 保持一个数据永远是原始数据不会被监听

unRef 、toRef、customRef

unRef :获取ref对象的原始数据,那为什么不用toRaw

toRaw连着value一起拿,获取出来就是 => {value:xxx}

unRef是ref专用 => xxx

toRef: 也是把一个数据转成ref对象,但是的ref专有一些区别

let json = {a:12}
const b = ref(json.a)
b.value++ 
console.log(json,b)  // {a:12} // {value:13}
const a = toRef(json,'a')
a.value++ 
console.log(json,a)  // {a:13} // {value:13}

ref toRef

相当于把原始数据拷贝,以后操作与原始数据无关 依然存在引用关系

改ref对象后模板会重新渲染 不会触发模板渲染

customRef:自定义ref

function myCustomRef(){
  let _val = 12 
  return customRef((track,trigger)=>{
    return {
      get(){
        track()
        return _val
      },
      set(newVal){
        _val = newVal
        // 通知vue,请重新渲染
        trigger()
      }
    }
  })
}
setup(){
    const arr = myAjax('xxxx',[])
    return {
        arr
    }
}
function myAjax(url,initval){
  let _data = initval 
  return customRef((track,trigger)=>{
    axios(url).then(res=>{
      _data = res._data
      trigger()
    })
    return {
      get(){
        track()
        return _data
      },
      set(newVal){
        _data = newVal
        // 通知vue,请重新渲染
        trigger()
      }
    }
  })
}

Vue2                     |                Vue3

--------------------------------------------------

beforeCreate             |             setup(替代)

created                   |             setup(替代)

beforeMount            |            onBeforeMount

mounted                   |            onMounted

beforeUpdate             |               onBeforeUpdate

updated                   |               onUpdated

beforeDestroy             |              onBeforeUnmount

destroyed                 |               onUnmounted

errorCaptured             |               onErrorCaptured

4. Teleport 组件

Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下渲染了 HTML

// vue3 新添加了一个默认的组件就叫 Teleport,我们可以拿过来直接使用,它上面有一个 to 的属性,它接受一个css query selector 作为参数,这就是代表要把这个组件渲染到哪个 dom 元素中
  <teleport to="#modal">
    <div id="center">
      <h1>this is a modal</h1>
    </div>
  </teleport>

4.1 Suspense - 异步组件好帮手

定义一个异步组件,在 setup 返回一个 Promise,AsyncShow.vue

<template>
  <h1>{{result}}</h1>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  setup() {
    return new Promise((resolve) => {
      setTimeout(() => {
        return resolve({
          result: 42
        })
      }, 3000)
    })
  }
})
</script>

使用 async await 改造一下异步请求, 新建一个 DogShow.vue 组件

<template>
  <img :src="result && result.message">
</template>
<script lang="ts">
import axios from 'axios'
import { defineComponent } from 'vue'
export default defineComponent({
  async setup() {
    const rawData = await axios.get('https://dog.ceo/api/breeds/image')
    return {
      result: rawData.data
    }
  }
})
</script>
<Suspense>
  <template #default>
    <async-show />
    <dog-show />
  </template>
  <template #fallback>
    <h1>Loading !...</h1>
  </template>
</Suspense>

5. 路由Vue-router

5.1 创建路由

// Vue2
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes:  [
    // 路由配置不变
  ]
})
// Vue3
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes:  [
    // 路由配置不变
  ]
})

5.2 使用路由

// Vue2
export default {
  name: "Home",
  methods: {
    goHome() {
      this.$router.push('Home')
    }
  }
};
// Vue3
export default {
  setup() {
    const router = useRouter()
    const goHome = () => router.push('Home')
    return { goHome};
  }
};

6.0 统一状态管理Vuex

6.1 创建Vuex

// Vue2
export default new Vuex.Store({
  state: {
    count:1
  },
  mutations: {
    inc(state){
      state.count ++ 
    }
  },
  actions: {
  },
  modules: {
  }
})
// Vue3
export default Vuex.createStore({
  state: {
    count:1
  },
  mutations: {
    add(state){
      state.count ++ 
    }
  },
  actions: {
  },
  modules: {
  }
});

6.2 使用Vuex

// Vue2
export default {
  name: "Home",
  data() {
    return {
        state: this.$store.state
    };
  },
  computed: {
    double() {
      return this.$store.state.count * 2;
    },
  },
  methods: {
    add() {
      this.$store.commit("add");
    }
  }
};
// Vue3
import { computed,  reactive } from "vue";
import { useStore } from "vuex";
export default {
  setup() {
    const store = useStore()
    const state = store.state
    const double = computed(() => store.state.count * 2)
    const add = () => {
      store.commit("add");
    };
    return { state, add ,double};
  }
};
相关文章
|
4天前
|
JavaScript 开发工具 容器
初始Vue、Vue模板语法、数据绑定(2022/7/3)
这篇文章是关于Vue.js基础的介绍,包括Vue的简介、安装使用、开发工具、基础知识、模板语法和数据绑定。文中通过代码实例和页面效果展示了如何创建Vue实例、使用插值和指令语法、以及单向和双向数据绑定的方法。
初始Vue、Vue模板语法、数据绑定(2022/7/3)
|
4天前
|
JavaScript 开发工具 git
Vue学习之--------脚手架的分析、Ref属性、Props配置(2022/7/28)
这篇文章分析了Vue脚手架的结构,并详细讲解了`ref`属性和`Props`配置的基础知识、代码实现和测试效果,展示了如何在Vue组件中使用`ref`获取DOM元素或组件实例,以及如何通过`Props`传递和接收外部数据。
Vue学习之--------脚手架的分析、Ref属性、Props配置(2022/7/28)
|
4天前
|
缓存 JavaScript
Vue学习之--------计算属性(2022/7/9)
这篇文章通过代码实例和效果测试,详细讲解了Vue计算属性的概念、实现方式、优势以及与插值语法和methods的区别。
Vue学习之--------计算属性(2022/7/9)
|
4天前
|
JavaScript
Vue学习之--------监视属性(2022/7/10)
这篇博客文章详细介绍了Vue框架中的监视属性(watch)功能,通过天气案例展示了监视属性的基础知识、代码实例、测试效果、深度监视、监视属性简写以及在项目中的实际应用。
|
6天前
|
API
VUE3——如何挂载全局属性和方法
VUE3——如何挂载全局属性和方法
21 0
|
10天前
|
存储 JavaScript 前端开发
响应式的 switchboard:让又大又慢的Vue/AIpine 页面爆快
响应式的 switchboard:让又大又慢的Vue/AIpine 页面爆快
|
1月前
|
缓存 JavaScript 前端开发
前端框架与库 - Vue.js基础:模板语法、数据绑定
【7月更文挑战第14天】Vue.js 是渐进式框架,以简洁API和高效数据绑定知名。本文聚焦模板语法与数据绑定,解释常见问题和易错点,助力初学者避坑。模板语法中,{{ expression }} 用于渲染值,v-bind/: 用于动态绑定属性。数据绑定涉及文本、属性和事件,注意v-model适用于表单元素,计算属性有缓存。理解正确用法,借助文档和IDE,可提升开发质量和效率。善用Vue.js,打造响应式UI。
|
1月前
|
API
vue3 原理【详解】Proxy 实现响应式
vue3 原理【详解】Proxy 实现响应式
26 0
|
3天前
|
JavaScript
Vue中如何设置在执行删除等危险操作时给用户提示(二次确认后执行对应的操作)
这篇文章介绍了在Vue项目中如何实现执行删除等危险操作时的二次确认机制,使用Element UI的`el-popconfirm`组件来弹出确认框,确保用户在二次确认后才会执行删除操作。
Vue中如何设置在执行删除等危险操作时给用户提示(二次确认后执行对应的操作)