VUE3 和 VUE2 的不同

167 阅读4分钟
1.reactive具有深层响应式

在vue2中针对一个复杂数据的修改有时会存在vue监听不到的情况,(对象增加和删除的属性,通过下标修改数组的值),这时往往需要用到this.$set(数组/对象名,下标/属性名,新值)或者this.forceUpdate()让修改的数据被捕捉到。

或者watch监听一个对象时,如果对象属性还是个对象那么就需要deep: true才能监听到改变。

但是在vue3中,复杂数据类型用reactive()方法声明后会具有深层响应性,对对象和数组的(对象增加和删除的属性,通过下标修改数组的值)修改会被捕捉到。对对象深层次修改也会监听到。

image.png

2.nextTick(fn(){})

vue2中往往在组件实例中使用this.$nextTick(fn(){})等待下一次 DOM 更新刷新。vue3中使用nextTick(fn(){})

并且nextTick()的返回结果是promise

使用方法1:nextTick(fn(){回调函数})

使用方法2:结合await

image.png

3.子组件获取父组件的数据 props/defineProps()

vue2中通常使用props:['','']props: {a: {},b: {}}的方式

vue3非setup语法糖,与vue2类似,需要传参到setup函数中

export default defineComponent({
  props: ['b', 'a'],
  setup(props) {
     return{props}
  }
})

vue3setup语法糖

<script setup>
const props = defineProps(['a','b'])
</script>
4.父组件获取子组件的数据和方法 defineExpose

vue2中父组件获取子组件的数据常用的方法

<sonComponent ref="aa"></sonComponent>
···
this.$refs.aa.变量名/方法名
或
this.$children[n].***    获取下标第几个的子组件

vue3中:

image.png

1.子组件使用的选项式API(vue2风格)或者没有使用setup语法糖,那么使用子组件的数据和方法

<son ref="aa"></son>
···
const aa = ref(null)
onMounted(()=>{ aa.value.变量名/方法名 })

2.子组件使用了setup语法糖,子组件需要defineExpose显式的暴露自己的变量和函数,父组件才可以使用子组件的暴露的内容。

父组件
<son ref="aa"></son>
···
const aa = ref(null)
onMounted(()=>{ aa.value.变量名/方法名 })

子组件
let a = ref('a')
function b(){}
defineExpose({ a,b })               defineExpose显式的暴露
5.模板引用 ref获取DOM元素或子组件

vue2中通常使用this.$refs.***获取DOM元素本身或者vue组件实例

vue3中

单个DOM: html: <p ref="p">hello</p> js:const p = ref(null)即可

多个DOM: html:<p v-for="item in 3" ref="p">hello</p> js:const pArr = ref([])即可

注意使用dom的时机

6.子组件事件触发父组件方法 emits/defineEmits

vue2中通常使用

this.$emit('自定义事件名',参数)

vue3中:

没有使用setup语法糖,需要使用emits并且传入setup第二个参数中

export default{
  emits: ['自定义事件名a','自定义事件名b'],
  setup(props, ctx){
    ctx.emit('自定义事件名a', 参数)
  }
}

使用了setup语法糖,需要使用defineEmits方法:

const emit = defineEmits(['自定义事件名a','自定义事件名b'])
emit(自定义事件名a, 参数)
7.watch监听器

vue2中对对象的深层监听需要手动开启,在vue3中reactive具有深层响应式,所以watch监听对象时默认开始深层监听。

watch(对象名,(new,old)=>{***})

深度侦听需要遍历被侦听对象中的所有嵌套的属性,当用于大型数据结构时,开销很大。因此请只在必要时才使用它,并且要留意性能。只需要监听复杂对象的某个属性时,使用

watch(()=>对象名.属性名,(new,old)=>{***})

vue3中新增了watchEffectAPI,它与watch不同在于,它没有明确指定依赖哪个数据,函数中用到的数据都是它的依赖数据,当依赖的数据发生改变时就会执行函数。

watchEffect(() => {***})

image.png

8.注册全局组件

vue2:

import Vue from "vue";
import zujian from '**'
Vue.component('组件名', zujian)

vue3:

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
import zujian from '**'
app.component('组件名', zujian)         app.component().component().component()方法可以被链式调用
9.具名插槽

vue2的使用办法:

子组件:
<slot name="aa"></slot>

父组件两种办法:
<div slot="aa">123456789</div>
<template v-slot:aa>123456789</template>            v-slot:  可简写为 #

vue3的使用办法:

子组件:
<slot name="aa"></slot>

父组件:
<template v-slot:aa>123456789</template>            v-slot:  可简写为 #
10.异步组件 defineAsyncComponent

在大型项目中,我们可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件,会发送请求。 vue2中:

components: {
  componentA: ()=> import('***')
}

更多细节

vue3中:

  const componentA = defineAsyncComponent(()=> import('***'))
  更多配置
  const AsyncComp = defineAsyncComponent({ 
    loader: () => import('./Foo.vue'), 
    loadingComponent: LoadingComponent, 
    delay: 200,  
    errorComponent: ErrorComponent, 
    timeout: 3000 
  })

更多细节

11.逻辑复用 组合式函数

vue2中推荐使用mixins vue3中推荐使用组合式函数,组合式函数与普通导出的函数的区别是可以使用vue里提供给的api

12.状态管理

vue3推荐使用菠萝,也可以使用vuex,

vue2使用this.$store.***具有响应式 vue3使用useStore()函数,想要具有响应式要在计算变量中声明,且useStore()在刚进去就执行,否则会出现莫名其妙的错误,求告知。

而且直接使用let store = useStore()store.state.**不具有响应式,当vuex改变时store不会改变。使用计算属性computed(() => store.state.**)使其具有响应式。

13.路由缓存

今天使用老方法实现路由缓存,发现失败了,进而发现vue3的路由缓存和vue2的实现方法不一样。路由缓存是指将在该路径下的组件在切换时不进行销毁,而是存入缓存中,当路径改变再次切换回来时会保持离开时的状态。

vue2的实现方法:

<keep-alive>
    <router-view />
</keep--alive>

vue3的实现方法:

<router-view v-solt="{ Component }">
    <keep-alive>
        <component :is="Component" />
    </keep-alive>
</router-view>

<keep-alive>可以通过includeexclude决定哪些组件可以存入缓存,哪些组件不能存入缓存,匹配的是组件里的name。

vue3组件的name : 当使用了setup语法糖时,单文件组件会自动根据文件名生成对应的 name 选项 例如 Tree.vue 那他的name 就是 Tree 自动生成。当没有使用setup语法糖时可以自己name:**定义。

查漏补缺
v-show不支持在template标签上使用
v-for="item in arr" 可以写作 v-for="item of arr"
在事件处理中访问事件参数

1.<div @click="方法名(参数,$event)"></div>

2.<div @click="(event)=>方法名(参数,event)"></div>

v-model上的修饰符

1.lazy 更新数据的时机由input事件变为change事件

2.number 该值无法被 parseFloat() 处理,那么将返回原始值。

3.trim 同字符串.trim()方法,去除字符串两端空格

组件名推荐使用帕斯卡命名法

<MyComponent>

image.png

传递props推荐使用kebab-case形式

aa-bb-cc烤肉串形状

image.png

监听子组件的事件推荐使用kebab-case形式

image.png