Vue3实践指南二 —— Vue3性能提升分析

2,429 阅读4分钟

前言

前一篇文章,我们简单介绍了一些Vue3以及Vue3的简单的项目搭建,然而,上一篇文章也还遗留了一个小问题。今天就来聊聊Vue3为性能优化所做的工作(diff算法优化、hoistStatic静态提升、cacheHanlers事件监听器缓存、SSR)。

diff算法优化

了解过Vue2的朋友们肯定知道diff算法,所谓diff算法是Vue将模板编译成渲染函数生成虚拟DOM树,通过递归遍历两个虚拟DOM树,并比较每个节点上的每个属性,来确定实际DOM哪些部分需要更新。虽然经过现代JS引擎执行的高级优化之后,这种算法非常快速,但是在实际使用中DOM的更新仍然设计到许多不必要的工作(具体表现在静态内容,只有少量动态模板的情况)。 比如下面这段代码

<div>
    <p>老八食堂</p>
    <p>{{ message }}</p>
</div>

vue2的diff全量对比:

image.png

而在Vue3中使用patchFlag(静态标记)对diff算法进行了优化,在创建虚拟DOM时,根据DOM内容是否会发生变化,而给与相应类型的patchFlag。在更新前节点进行比较的时候,只会去对比带有静态标记的节点

image.png

通过上图,Vue3的diff算法只对带有静态标记的DOM进行比较,只需要对比一次,而Vue2中的diff算法却比较了3次。这便是Vue3比Vue2性能好的一个原因。 接下来我们通过模板转化网站 把模板转化成虚拟DOM来验证一些上述分析: image.png 观察上图可以发现,message对应的P标签有个注释为TEXT的1,这个1就是patchFlag。而Vue3对不同类型的元素会有不同的flag标记,下面把Vue3源码中的Flag类型贴上:

export const enum PatchFlags { 
    TEXT = 1,// 动态的文本节点 
    CLASS = 1 << 1, // 2 动态的 class 
    STYLE = 1 << 2, // 4 动态的 style 
    PROPS = 1 << 3, // 8 动态属性,不包括类名和样式 
    FULL_PROPS = 1 << 4, // 16 动态 key,当 key 变化时需要完整的 diff 算法做比较 
    HYDRATE_EVENTS = 1 << 5, // 32 表示带有事件监听器的节点 
    STABLE_FRAGMENT = 1 << 6, // 64 一个不会改变子节点顺序的 
    Fragment KEYED_FRAGMENT = 1 << 7, // 128 带有 key 属性的 Fragment 
    UNKEYED_FRAGMENT = 1 << 8, // 256 子节点没有 key 的 Fragment 
    NEED_PATCH = 1 << 9, // 512 
    DYNAMIC_SLOTS = 1 << 10, // 动态 solt 
    HOISTED = -1, // 特殊标志是负整数表示永远不会用作 diff 
    BAIL = -2 // 一个特殊的标志,指代差异算法 
}

hoistStatic 静态提升

我们在平时开发中,会将一些常量提升出去定义,如下所示:

const PAGE_SIZE = 20
function getDate() {
    $.get({
        url: '',
        data: {
            pageSize: PAGE_SIZE
        }
    })
}

如上面的例子,如果我们将PAGE_SIZE写在getData内,每次调用都会重新定义一次PAGE_SIZE变量。 在Vue3中也做了类似上面的优化,Vue3的编译器会将模板中的静态节点、子树、数据对象,并在生成的代码中将他们提升到渲染函数之外,一次来避免每次调用渲染函数的时候重新创建这些对象,从而大大提高内存使用率并减少垃圾回收频率。 当然这样解释有点抽象,我们依然可以通过模板转化网站来直观的感受一下: image.png 上图中红框圈起来的地方,将模板中的静态模板提升到了render函数外,这又提升了Vue的性能。

cacheHandlers 事件监听缓存

默认情况下onClick会被视为动态绑定,所以每次都会追踪他的变化。但是函数还是同一个函数所以没必要追踪,直接缓存起来复用就好了,这就是所说的事件监听缓存。Vue3就做了这一缓存机制去提升性能。 下图为未开启事件缓存时的模板编译,会将click事件添加上flag类型: image.png

如果勾选上cacheHandlers,如下图编译,没有了静态标记,也就是说,不会进行动态更新时的比较: image.png

SSR 渲染

在Vue2中也有SSR渲染,,但是Vue3中的SSR渲染相对于Vue2也有了很大的性能提升。

当你在开发中使用 SSR 开发时,Vue 3.0 会将静态标签直接转化为文本,相比 React 先将 jsx 转化为虚拟 DOM,再将虚拟 DOM 转化为 HTMLVue 3.0 已经赢了。

image.png

总结

本文分析了Vue3在性能上的重大提升,有些方面的设计甚至超过了React,如今Vue3大行其道,面试官们也会将面试题迁移到Vue3上。所以,对Vue3学起来吧,骚年们。