一、重写双向数据绑定,proxy代替Object.defineProperty做数据劫持
### Vue2.x 中由于 Object.defineProperty的缺陷,存在如下问题:
- 对于Object,无法检测属性的“增加”和“移除”
- 对于Array, 无法检测数组的长度变更和 数组下标值的变化
eg: data () {
return {
obj:{ a: 1, b: 2 },
arr: [1,2,3]
}
},
obj.c = 3; delete obj.a
arr[3] = 4; arr.length = 2
说明:以上两种情况:此时数据已经发生变化,但是不是响应式的,视图不会更新 。可用$set解决这个问题.具体详情: https://v2.cn.vuejs.org/v2/guide/reactivity.html
### Vue3.x 中利用Proxy和Reflect做数据劫持,完美的解决了这个缺陷;同时避免了Vue2中对于深层的嵌套属性的遍历。提升了性能。
<script setup>
import { reactive } from 'vue'
const nestedObj = reactive({
a: 1,
b: 2,
foo:{
bar: 3
}
})
const changeObj = () =>{
nestedObj.c = 4;
nestedObj.foo.bar = 5 //数据变化,视图同时发生改变。
}
</script>
二、TreeShaking支持
vue3中全局API以及<keep-alive>,<teleport>都做了TreeSkaking支持,通过webpack 等打包工具,如果只是在组件内部引入,而没有使用,不会打到包里;代码体积会更小。
三、重构了虚拟DOM,优化了Diff算法,增加事件监听缓存
<template>
<div id="app">
<p>a</p>
<p>a</p>
<p>a</p>
<p>{{count}}</p>
</div>
</template>
如上图所示,vue2中对于新旧虚拟DOM对比,是全量对比,比如p标签中a,静态内容,仍然进行Diff;而在Vue3中,增加静态标记patch flag, 跳过静态内容,只比较动态内容,减少了消耗。
TEXT = 1 // 动态文本节点
CLASS=1<<1,1 // 2//动态class
STYLE=1<<2,// 4 //动态style
PROPS=1<<3,// 8 //动态属性,但不包含类名和样式
FULLPR0PS=1<<4,// 16 //具有动态key属性,当key改变时,需要进行完整的diff比较。
HYDRATE_ EVENTS = 1 << 5,// 32 //带有监听事件的节点
STABLE FRAGMENT = 1 << 6, // 64 //一个不会改变子节点顺序的fragment
KEYED_ FRAGMENT = 1 << 7, // 128 //带有key属性的fragment 或部分子字节有key
UNKEYED FRAGMENT = 1<< 8, // 256 //子节点没有key 的fragment
NEED PATCH = 1 << 9, // 512 //一个节点只会进行非props比较
DYNAMIC_SLOTS = 1 << 10 // 1024 // 动态slot
HOISTED = -1 // 静态节点
BALL = -2
事件缓存: 对于在Vue2中对于事件绑定,比如click事件,每次触发都会生成一个新的function,在Vue3中提供了cachehandlers,当cachehandlers开启,会把函数存入缓存,下次触发,直接从缓存中取即可。
四、更好的类型推导,支持TypeScript
Vue3源码从flow换成了ts,在项目中配合ts,可以做类型检查;更好的规范代码
五、新功能和特性
createRenderer API from @vue/runtime-core to create custom renderers
Suspense experimental
五、新的工具链
Vite:新的构建工具,提升开发体验
Volar : IED 智能插件
...