1. 双向数据绑定原理
vue2 是结合发布者订阅者模式,结合es6Object.defineProperty() 对数据进行劫持,进一步通过vue中的watcher的update 实现双向数据绑定。 vue3 中使用了es6的proxy 进行数据代理。
相对于vue2,使用proxy的优势:
- defineProperty只能监听某个属性,不能对全对象监听;
- 可以监听到数组内部的变化;
- vue2中我们给对象添加一个新属性,它不会更新到视图上,只是因为新添加的属性并没有通过Object.defineProperty()进行响应式设置,但是vue3中的proxy对于动态添加的属性也是具有响应式的.
2. vue3支持碎片
也就是说,vue3在组件中支持多个根节点.
vue2
<template>
<div>
<h1></h1>
</div>
</template>
vue3
<template>
<div>
<h1></h1>
</div>
<div>
<span></span>
</div>
</template>
3. Composition API (组合api)
vue2和vue3最大的区别就是,vue3使用了Composition API (组合api)
在vue2中是使用的Options API,这种写法不方便我们的阅读和交流,逻辑过于分散。
vue2
<script>
export default {
data() {
return {};
},
mounted() {},
methods: {},
computed: {},
components:{}
};
</script>
vue3
这样代码会更加简洁和整洁。
<script>
export default {
setup() {
}
};
</script>
4. 生命周期钩子
Vue2--------------vue3
beforeCreate -> setup() 比beforeCreate和created执行的还要早
created -> setup()
beforeMount -> onBeforeMount 组件挂载到节点之前执行的函数
mounted -> onMounted 组件挂载完成后执行的函数
beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数
updated -> onUpdated 组件更新完成之后执行的函数
beforeDestroy -> onBeforeUnmount 组件卸载之前执行的函数
destroyed -> onUnmounted 组件卸载完成后执行的函数
若组件被keep-alive包含,则会多出两个钩子函数:
activated -> onActivated 组件激活时触发
deactivated -> onDeactivated 组件失活时触发
5. 父子传参不同,setup()函数
因为在setup 里面是获取不到this ,所以在vue3中我们通过setup(props,context) 两个参数进行父子之间的传参。
vue2
# 父组件
<template>
<div class='father'>
<my :msg="msg" @get="get"></my>
{{sonMsg}}
</div>
</template>
<script>
import my from '@/components/my'
export default {
data() {
return {
msg:'父组件的数据',
sonMsg:''
};
},
methods: {
get(val) {
this.sonMsg = val
console.log(val);
}
},
components:{
my
}
};
</script>
# 子组件
<template>
<div class='son'>
{{msg}}
<button @click="handler">点击获取数据</button>
</div>
</template>
<script>
export default {
props:["msg"],
methods:{
handler() {
this.$emit('get','子组件的数据')
}
}
};
</script>
vue3
# 父组件
<template>
<div class='father'>
<my :msg="msg" @get="get"></my>
{{sonMsg}}
</div>
</template>
<script>
import my from '@/components/my'
import { reactive,toRefs } from 'vue'
export default {
setup() {
const obj = reactive({
msg:'父组件的数据',
sonMsg:''
})
const get = (val) =>{
console.log(val);
obj.sonMsg = val
}
return {
...toRefs(obj),
get
}
},
components:{
my
}
};
</script>
# 子组件
<template>
<div class='son'>
{{msg}}
<button @click="handler">点击获取数据</button>
</div>
</template>
<script>
export default {
props:["msg"],
setup(props,{attrs,slots,emit}) {
const handler = ()=>{
emit('get','子组件的数据')
}
return {
handler
}
}
};
</script>
6. 移除了filter过滤器
在vue3中,移除了filter,我们可以使用计算属性进行代替
7. vue2和vue3的diff算法
vue2
vue2 diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。 vue2 diff算法会比较每一个vnode,而对于一些不参与更新的元素,进行比较是有点消耗性能的。
vue3
vue3 diff算法在初始化的时候会给每个虚拟节点添加一个patchFlags,patchFlags就是优化的标识 。 只会比较patchFlags发生变化的vnode,进行更新视图,对于没有变化的元素做静态标记,在渲染的时候直接复用。
8. v-if 和 v-for的优先级
vue2 我们最好不要把v-if 和v-for 同时用在一个元素上,这样会带来性能的浪费(每次都要先渲染才会进行条件判断)
v-for 优先于 v-if 生效
<div v-if="index == 1" v-for="(item,index) in arr" :key="index">{{item}}</div>
vue3
v-if 优先于 v-for 生效
<div v-if="index == 1" v-for="(item,index) in arr" :key="index">{{item}}</div>
vue中会给我们报警告: 意思就是:属性“index”在渲染期间被访问,但未在实例上定义(v-if先进行判断,但是这时候v-for还没有渲染,所以index是找不到的)
了解更多vue3的官网
|