响应式系统提升
-
Vue2.0中响应式系统的核心defineProperty
在初始化时会遍历data中的所有成员,通过defineProperty将对象的属性转换为getter和setter,如果对象中的成员又是对象的话需要递归处理里面的每一个属性,因为是在初始化时进行的defineProperty,所以没有使用的属性也进行了响应化处理
-
Vue3.0中使用Proxy对象重写响应式系统
使用的Es6后新增的Proxy对象,本身性能就比defineProperty要好。另外代理对象可以拦截属性的访问、赋值、删除等操作,不需要初始化时遍历所有的属性。另外多层嵌套属性只有在访问时才会递归处理下一层属性
-
可以监听动态新增的属性,vue2.0中需要调用vue.set()进行处理
-
可以监听删除的属性,vue2.0监听不到属性的删除
-
可以监听数组的索引和length属性,vue2.0监听不到这两个属性的操作
使用Proxy提升了响应式的性能和功能
-
编译优化
通过优化编译过程和重写虚拟DOM让首次渲染和更新的性能有了大幅度提升
-
vue2中通过标记静态根节点优化了diff的过程
V2.0中模板首先要编译成render函数,这个过程在构建过程中完成,在编译时会编译静态根节点和静态节点,静态根节点中要求必须有一个静态子节点,当组件的状态发生变化后会触发watcher的update,最终去执行虚拟DOM的patch操作,遍历所有虚拟节点找到差异,更新到真实DOM上。diff的过程中会比较整个虚拟DOM,先对比新旧的div以及它的属性,然后再对比它的子节点,vue2中渲染的最小单位是组件。vue2中diff的过程会跳过静态根节点,因为静态根节点的内容不会发生变化,也就是vue2中通过标记静态根节点优化了diff的过程,但是静态节点还需要diff,这个过程没有被优化。
-
vue3中标记和提升所有的静态节点,diff时只需要对比动态节点内容
- 新引入Fragments(片段)特性,模板中不需要再创建一个唯一的根节点,模板里可以直接放文本内容或者很多同级的标签
- 静态提升,静态节点都会被提升到render 的外部,只有初始化时会被创建,再次调用render时不会再次创建,可以直接重用这些静态节点对应的vnode
- Patch flag
- 缓存事件处理函数减少了不必要的更新操作
源码体积的优化
- Vue3中移除了一些不常用的API
- 例如:inline-template、filter等可以让最终代码的体积变小
- 对Tree-shaking支持更好,Tree-shaking依赖Es-module,也就是export import。通过编辑阶段的静态分析找到没有引入的模块在打包时直接过滤掉,让打包后的体积更小。