vue3的优化

226 阅读3分钟

响应式优化——proxy Api

  • defineProperty API 的局限性最大原因是它只能对单例属性做监听。 vue2.x的响应式实现是基于defineProperty中的descriptor,对data中的属性进行遍历+递归,为每个属性设置了getter、setter。所以vue只能对data中预定义过的属性做出响应。使用下标直接修改属性的值或者添加一个预先不存在的对象属性是无法做到setter监听的。
  • proxy API的监听是针对一个对象的,有13种拦截方式,完全可以代理所有属性,会带来很大的性能提升和更优的代码。
  • 响应式是惰性的。vue 2.x中,对深层属性嵌套的对象,要劫持它内部深层次的变化,就需要递归遍历对象,执行Object.defineProperty把每一层对象数据都变成响应式的,有很大性能消耗。vue3.x中。proxy API 并不能监听到对象内部深层次的属性变化,因此它在getter中去递归响应式,真正访问到的内部属性才会变成响应式,按需实现响应式,减少性能消耗

编译优化

block tree

vue2.x中数据更新并触发重新渲染的粒度是组件级的,单个组件内部需要遍历该组件的整个vnode树。在vue2.0中,渲染效率的快慢与组件大小成正相关;组件越大,渲染效率越慢。并且对于无数据更新的静态节点来说,这些遍历都是性能浪费。 vue3.0通过编译阶段对静态模板的分析,编译生成了block tree。block tree是一个将模板基于动态节点指令切割的嵌套区块,每个区块内部的节点结构是固定的,只需要追踪自身包含的动态节点。在3.0中,渲染效率不在于模板大小成正相关,而是与模板中动态节点的数量成正相关。

slot编译优化

vue2.x中如果一个组件传入了slot,每次父组件更新的时候,会强制使子组件update,造成性能的浪费。vue3.0优化slot的生成,使得非动态slot中属性的更新只会触发子组件的更新。动态slot是指在slot上面使用v-if,v-for,动态slot名字等会导致slot产生运行是动态变化但是又无法被子组件track的操作。

diff算法优化

vue 2.x中的虚拟dom是进行全量的对比。vue3.0中新增了静态标记(patchflag):在与上次虚拟节点进行对比的时候,只对比带有patch flag的节点,并且可以通过flag的信息得知当前节点要对比的具体内容变化。

hoist static静态提升

vue2.x中,无论元素是否参与更新,每次都会重新创建。vue3.0对不参与更新的元素,只会创建一次,之后每次渲染不停复用

cache handlers事件侦听器缓存

默认情况下onclick会被视为动态绑定,所以每次都会追踪它的变化但是因为是同一个函数,直接缓存起来复用即可。