zoukankan      html  css  js  c++  java
  • Vue3教程:Vue 3.x 快在哪里?

    人云亦云,并不会让你变得有多优秀,而会让你越来越随大流。

    当你和别的开发在聊到 Vue 3.0 版本发布,有哪些亮点时,你的答案之一肯定有“它变得更快了,性能上快了 1.2 ~ 2倍”。

    那么我就想问你,是什么让 Vue 变快了,尤大已经在 beta 版的线上直播上告诉了我们答案。

    PatchFlag(静态标记)

    Vue 2.x 中的虚拟 DOM 是全量对比的模式,而到了 Vue 3.0 开始,新增了静态标记(PatchFlag)。

    在更新前的节点进行对比的时候,只会去对比带有静态标记的节点。并且 PatchFlag 枚举定义了十几种类型,用以更精确的定位需要对比节点的类型。下面我们通过图文实例分析这个对比的过程。

    假设我们有下面一段代码:

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

    在 Vue 2.x 的全量对比模式下,如下图所示:

    通过上图,我们发现,Vue 2.x 的 diff 算法将每个标签都比较了一次,最后发现带有 {{ message }} 变量的标签是需要被更新的标签,显然这还有优化的空间。

    在 Vue 3.0 中,对 diff 算法进行了优化,在创建虚拟 DOM 时,根据 DOM 内容是否会发生变化,而给予相对应类型的静态标记(PatchFlag),如下图所示:

    观察上图,不难发现视图的更新只对带有 flag 标记的标签进行了对比(diff),所以只进行了 1 次比较,而相同情况下,Vue 2.x 则进行了 3 次比较。这便是 Vue 3.0 比 Vue2.x 性能好的第一个原因。

    我们再通过把模板代码转译成虚拟 DOM,来验证我们上述的分析是否正确。我们可以打开模板转化网站,对上述代码进行转译:

    上图蓝色框内为转译后的虚拟 DOM 节点,第一个 P 标签为写死的静态文字,而第二个 P 标签则为绑定的变量,所以打上了 1 标签,代表的是 TEXT(文字),标记枚举类型如下:

    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 = 10
    function getData () {
    	$.get('/data', {
      	data: {
        	page: PAGE_SIZE
        },
        ...
      })
    }
    

    诸如上述代码,如果将 PAGE_SIZE = 10 写在 getData 方法内,每次调用 getData 都会重新定义一次变量。

    Vue 3.0 在这方面也做了同样的优化,继续用我们上一个例子写的代码,观察编译之后的虚拟 DOM 结构,如下所示:

    没有做静态提升前:

    选择 Option 下的 hoistStatic

    静态提升后:

    细心的同学会发现, 老八食堂 被提到了 render 函数外,每次渲染的时候只要取 _hoisted_1 变量便可。认真看文章的同学又会发现一个细节, _hoisted_1 被打上了 PatchFlag ,静态标记值为 -1 ,特殊标志是负整数表示永远不会用作 Diff。也就是说被打上 -1 标记的,将不在参与 Diff 算法,这又提升了 Vue 的性能。

    cacheHandler(事件监听缓存)

    默认情况下 @click 事件被认为是动态变量,所以每次更新视图的时候都会追踪它的变化。但是正常情况下,我们的 @click 事件在视图渲染前和渲染后,都是同一个事件,基本上不需要去追踪它的变化,所以 Vue 3.0 对此作出了相应的优化叫事件监听缓存,我们在上述代码中加一段:

    <div>
      <p @click="handleClick">屋里一giao</p>
    </div>
    

    编译后如下图所示(还未开启 cacheHandler):

    在未开启事件监听缓存的情况下,我们看到这串代码编译后被静态标记为 8,之前讲解过被静态标记的标签就会被拉去做比较,而静态标记 8 对应的是“动态属性,不包括类名和样式”。 @click 被认为是动态属性,所以我们需要开启 Options 下的 cacheHandler 属性,如下图所示:

    细心的同学又会发现,开启 cacheHandler 之后,编译后的代码已经没有静态标记(PatchFlag),也就表明图中 P 标签不再被追踪比较变化,进而提升了 Vue 的性能。

    SSR 服务端渲染

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

    ssr.jpg

    StaticNode(静态节点)

    上述 SSR 服务端渲染,会将静态标签直接转化为文本。在客户端渲染的时候,只要标签嵌套得足够多,编译时也会将其转化为 HTML 字符串,如下图所示:

    需要开启 Options 下的 hoistStatic

    总结

    以上便是 Vue3.0 在编译时针对虚拟 DOM 的性能优化,这使得 Vue 3.0 在性能上是 Vue 2.x 的 1.2~2倍。

    创建了一个 Vue3 的学习仓库 vue3-examples,仓库地址:https://github.com/newbee-ltd/vue3-examples,此仓库将不定期更新各种 Vue3.0 相关的知识及各种整合 Demo 及 Vue3 使用小技巧,大家可以关注一下,有什么建议也欢迎大家给我留言。

    除注明转载/出处外,皆为作者原创,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

  • 相关阅读:
    改写历史,永久删除git库的物理文件
    双调排序
    GitHub从无到有
    Nginx的安装与基本应用
    Django从无到有的艰苦历程
    pycharm 相关设置问题
    ORM介绍
    Django中的过滤器
    FBV和CBV的差异
    django中models field详解
  • 原文地址:https://www.cnblogs.com/han-1034683568/p/14094539.html
Copyright © 2011-2022 走看看