Vue3 的新特性(四) —— 虚拟DOM的底层原理

目录

前言

Vdom (虚拟dom)凭借着出色的性能成为了目前的主流的前端框架都会选择的渲染方案。再加上优秀的 diff 算法对它的一步步的优化,使框架的价值得到了极致的体现,几乎成为了我们前端开发必不可少的方案。

我们已经知道,Vue2.x 中的 Vdom 已经相当出色了,性能非常优秀。不过令人兴奋的是,尽管它够快,但在 Vue3 中还是对 Vdom 进行了重写,使 Vue3 突破了 Vdom 的性能瓶颈,更快!

Vue3 如何重写 Vdom

在开始介绍之前,先给大家推荐一个网站:[https://vue-next-template-explorer.netlify.app]

这是 Vue3 官方的演示 Vdom 的示例网站,本篇文档也是基于它进行演示。

1. 入门

  • 当我们创建一个这样的静态 dom 元素的时候:

    真实DOM
  • Vue3 给我们编译后的 Vdom 是这个样子的:

    虚拟dom

看似比较复杂,实际上 _createBlock 函数中才是我们创建的 dom,从它身上我们可以看出,我们创建了一个 span 元素,内容为 “Hello World!”。这就是 Vdom 最基础的形式,在这里我们并不会感觉到 Vue3 与 Vue2 有什么不同。

2. patch flag 优化静态树

  • 当我们创建了一个动态的 dom 元素:

    真实动态dom
  • Vue3 编译后的 Vdom 是这个样子的:

    虚拟动态dom

我们发现创建动态 dom 元素的时候,Vdom 除了模拟出来了它的基本信息之外,还给它加了一个标记: 1 /* TEXT */

这个标记就叫做 patch flag(补丁标记)

patch flag 的强大之处在于,当你的 diff 算法走到 _createBlock 函数的时候,会忽略所有的静态节点,只对有标记的动态节点进行对比,而且在多层的嵌套下依然有效。

尽管 JavaScriptVdom 的对比已经非常的快,但是 patch flag 的出现还是让 Vue3 的 Vdom 的性能得到了很大的提升,尤其是在针对大组件的时候。

3. patch flag 优化静态属性

1. 静态绑定

  • 当我们创建一个有属性的元素:

    有属性的DOM
  • Vue3 编译后的 Vdom 是这个样子的:

    有属性的Vdom

    让我们观察它的 patch flag ,发现并没有对 id 做特殊的标记。是因为 dom 元素的静态属性在渲染的时候就已经创建了,并且是不会变动的,在后面进行更新的时候,diff 算法是不会去管它的。

2. 动态绑定

  • 当我们创建一个属性是动态绑定的元素:

    动态属性元素
  • Vue3 编译后的 Vdom 是这个样子的:

    动态属性元素Vdom

    再观察它的 patch flag ,会发现变成了 9 /* TEXT, PROPS */,而且后边多了一个数组 ["id"]

    这里的 patch flag 中的注释的内容告诉我们,这一个 dom 元素不止有内容 TEXT 会变化,它的属性 PROPS 也会变化。而后边的数组中的内容则是有可能发生变化的属性。

看到这里,我们就会明白 Vue3 实际做的事情了。

Vue3 在 Vdom 的更新时,只会关注它有变化的部分。这样的优化使 Vue3 既跳出了 Vdom 的性能瓶颈,又依然保留了可以手写 render function 的灵活性。相当于 Vue3 既有 react 的灵活性,又有基于模板的性能保证。——尤雨溪

4. 静态提升

刚刚我们提到 Vue3 突破 Vdom 的性能瓶颈的方式是,只关注它有变化的部分。而在更新时具体是怎么做的呢?

具体的做法就是 静态树的提升静态属性的提升

  • 我们创建若干的 dom 元素:

    dom元素
  • 静态提升之后:

    静态提升后的dom元素

    我们已经知道处理后的 Vdom 都在 _createBlock 函数之中,而观察结果我们发现,所有的静态元素都被放在了 _createBlock 函数之外了,也就是说他们只会在页面初始的时候被渲染一次,而在更新的时候,静态元素是不予搭理的。

    这个优化就是 Vue3 的 静态提升

5. 事件侦听器缓存

了解 react 的同学都知道,在我们使用 react 时,对其性能优化的其中一点就是将侦听方法手动进行缓存,避免更新组件时被多次重新创建。而 Vue3 直接替我们做了这一点

  • 创建一个带有事件侦听的元素

    有事件侦听的dom
  • 没有进行事件侦听器缓存的 Vdom

    没有事件侦听缓存的Vdom

    在这里的 _createBlock 函数中就是这个元素的 Vdom 结构。观察高亮的地方,发现 onClick 函数以变量的形式存在。

  • 进行事件侦听器缓存后的 Vdom

    有事件侦听缓存的Vdom

    观察高亮的那一行,我们发现 onClick 函数的储存位置变成了缓存的形式。也就是说 当你的页面在不断的更新的时候,你的事件侦听器并不会重复地销毁再创建,而是以缓存的形式存在,这使 Vue3 在性能方面又有了一个出彩的地方。

    另外,Vue3 在 @click 中,直接手写内联函数也会被缓存起来,这一点是 react 做不到的。再加上 在 Vue3 中父组件的更新并不会直接触发子组件的更新,使得事件侦听器缓存在组件的层面可以提现出来更高的价值。

其他

以后的章节

总结

Vue3 在性能优化上的小方面,直接在编译的时候给你做到最好,这是它最有价值的地方。想必看完这些东西,你一定更期待 Vue3 的发布了!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349