文章目录
- 响应式系统优化
- 静态树提升
- diff算法优化
- Tree Shaking优化
- Composition API
- 事件缓存机制
响应式系统优化
Vue双向绑定原理
Proxy 相较于 Object.defineProperty 在性能上的优势主要体现在以下几个方面:
-
属性检测的全面覆盖:
-
Object.defineProperty
只能针对对象已有的属性进行劫持,对于对象属性的添加或删除无法做到监听。 -
而
Proxy
则可以代理整个对象,无论是属性的读取、赋值,还是添加新属性、删除属性,甚至是监听数组的变化等,Proxy 都可以做到。
因此,Proxy 提供了更全面的属性检测覆盖,减少了开发者需要手动处理特殊情况的代码量。
-
.
-
减少性能开销:
-
由于 Object.defineProperty 是针对每个属性进行劫持的,因此当对象属性较多时,会导致大量的性能开销。
vue2无法知道代码运行时具体会访问哪个属性,所以在初始化这个对象的时候,vue2只能采取递归遍历的方式把对象的每一层每一个属性都变成响应式,这就会影响页面的初始化渲染速度;
-
而 Proxy 是对整个对象进行代理,无需对每个属性进行单独处理,从而减少了性能开销。
对于多层嵌套的对象,由于proxy只能代理一层,所以vue3在真正访问到对象属性的时候,才去判断递归,而不是在初始化的时候就一股脑的递归。
.
-
-
更好的扩展性:
Proxy 是 ECMAScript 6 (ES6) 引入的新特性,相较于 Object.defineProperty 有着更好的扩展性和未来兼容性。随着 JavaScript 语言的不断发展和完善,Proxy 可能会得到更多的优化和改进,从而进一步提升性能。
. -
更高的灵活性:
Proxy 是直接代理整个对象。这意味着 Proxy 可以更加灵活地处理对象的各种操作,而不仅仅局限于属性的读写。
这种灵活性使得 Proxy 在处理复杂逻辑或特殊需求时更加得心应手。
静态树提升
静态树提升(Static Tree Hoisting)可以在编译阶段识别并提取出不会改变的静态节点,从而避免在每次渲染时重复计算这些节点,提高了组件的渲染性能,通过减少不必要的计算和DOM操作来加快页面的加载和更新速度。
-
在Vue2的编译中,有一个
optimize
过程,会对一些不会变化的DOM做静态标记。
一旦一个节点被标记为静态根节点,Vue就会生成一个staticRenderFns数组
来缓存这些静态节点的渲染函数。
这意味着在每次组件的渲染过程中,Vue可以直接调用这些缓存的渲染函数来生成静态节点的VNode,而不是每次都重新计算。此外,静态节点生成的VNode会带有
isStatic: true
的属性。在Vue的虚拟DOM diff算法中,会跳过对带有isStatic: true
属性的VNode这些节点的比较和更新,因为它们是静态的,不会改变。这进一步减少了不必要的DOM操作和比较,提高了渲染性能。 -
在Vue 3中,静态树提升不仅仅是对单个静态节点进行优化,而是将整个静态子树(即一组嵌套的静态节点)提升到父组件的渲染过程中。这意味着,在每次父组件重新渲染时,这个静态子树都会被直接复用,而不需要重新计算和创建。
通过这种方式,静态树提升能够显著减少渲染函数的复杂性,降低不必要的运行时开销,从而提高应用的性能和响应速度。尤其是在处理包含大量静态内容的组件时,静态树提升的效果尤为显著。
diff算法优化
Vue中的diff算法
-
静态标记与缓存
Vue 3在编译阶段会对静态节点进行标记,并在渲染过程中缓存这些静态节点。
这意味着在后续的更新中,Vue可以直接跳过这些静态节点的比较和渲染,从而减少了不必要的计算和DOM操作。
这种优化在大型应用中尤为显著,可以显著提高渲染性能。 -
动态节点的优化
除了静态节点,Vue 3还对动态节点进行了优化。
通过标记动态节点,Vue 3能够只对需要更新的节点进行比较和渲染,进一步提高了渲染性能。
这种优化对于频繁更新或具有大量动态内容的组件尤为有效。 -
事件代理与静态事件优化
Vue 3的diff算法还针对事件监听器进行了优化。
它采用了事件代理的方式,减少了事件监听器的数量,提高了性能。
此外,对于静态事件,Vue 3的diff算法会跳过不必要的比较和更新,只有在事件确实发生变化时才会触发组件的更新。 -
最长递增子序列
Vue 3的diff算法采用了最长递增子序列(Longest Increasing Subsequence,LIS)算法来找出最小的修改偏移量,优化节点移动时的操作,进一步减少了不必要的节点比较和更新操作,提高渲染性能。
LIS算法在diff过程中可以确定最少需要移动哪些节点来达到新的顺序,从而避免了不必要的节点重排。
Tree Shaking优化
Vue 3 提供了更好的 Tree Shaking 支持,可以消除代码中未使用的部分,减少了不必要的代码和模块,减少打包体积,从而降低了应用程序的加载时间和运行时的内存占用。
-
Vue 3通过静态树提升技术,能够在编译阶段就识别并移除模板中的静态部分,这意味着这些静态部分在最终的打包结果中不会占用任何空间。而Vue 2中,由于无法有效识别和处理静态内容,即使它们不会被使用,也会包含在最终的打包文件中,从而增加了体积。
-
Vue 3的源代码被重写为使用ES Modules格式,这使得Vue 3能够天然地支持Tree Shaking。ES Modules格式允许开发者将代码拆分成更小的、可复用的模块,并且只有在这些模块被实际使用时,才会被打包进最终的代码中。
Composition API
Vue3引入了Composition API,允许开发者将组件的逻辑分割成更小的、可复用的函数。这种模块化的设计使得代码更加清晰、易于维护,并且提高了组件的复用性,进一步提升了性能。
通过引入 Composition API,开发者可以更好地组织和复用逻辑代码,提高了代码的可维护性和可读性。
同时,Vue 3 还支持更多的特性,如片段(Fragments)、Teleport(传送门)和 Suspense(异步组件的悬挂状态)等,进一步丰富了组件的功能和用法。
事件缓存机制
Vue 3 引入了事件缓存机制,当事件被多次触发时,不会每次都执行事件处理函数,而是使用缓存的结果,从而减少了不必要的计算和处理时间,提高了应用程序的性能。
-
在 Vue 2.x 中,当绑定 DOM 事件(如
@click
)时,这些事件被视为动态变量。因此,每次视图更新时,Vue 都会追踪这些事件的变化,并在每次触发时重新生成新的函数。
这种机制在事件处理上可能产生不必要的开销。
-
在 Vue 3 中,通过引入事件
缓存对象 cacheHandlers
,这种机制得到了改进。当 cacheHandlers 开启时,
@click
等绑定的事件会被标记为静态节点,并放入 cacheHandlers 中。这样,在视图更新时,Vue 不会追踪这些静态事件的变化。当事件再次触发时,Vue 可以直接调用缓存的事件回调方法,而无需重新生成函数。