(三)Vue-Snabbdom

虚拟 DOM 的作用

  1. 维护视图和状态的关系
  2. 复杂视图情况下提升渲染性能
  3. 跨平台
    • 浏览器平台渲染DOM
    • 服务端渲染 SSR(Nuxt.js/Next.js)
    • 原生应用(Weex/React Native)
    • 小程序(mpvue/uni-app)等

Snabbdom

  1. Vue.js 2.x 内部使用的虚拟 DOM 就是改造的 Snabbdom •
  2. 大约 200 SLOC (single line of code) 3
  3. 通过模块可扩展
  4. 源码使用 TypeScript 开发 •
  5. 最快的 Virtual DOM 之一

导入 Snabbdom

  1. 安装 Snabbdom
    • npm intall snabbdom@2.1.0
  2. 导入 Snabbdom
    Snabbdom 的两个核心函数 init 和 h()
    • init() 是一个高阶函数,返回 patch()
    • h() 返回虚拟节点 VNode,这个函数我们在使用 Vue.js 的时候见过
  3. 文档中导入的方式


  4. 实际导入的方式
    parcel/webpack 4 不支持 package.json 中的 exports 字段


模块

模块的作用
  1. Snabbdom 的核心库并不能处理 DOM 元素的属性/样式/事件等, 可以通过注册 Snabbdom 默认提供的模块来实现
  2. Snabbdom 中的模块可以用来扩展 Snabbdom的功能
  3. Snabbdom 中的模块的实现是通过注册全局的钩子函数来实现的
官方提供的模块

•attributes
• props
• dataset
• class
• style
• eventlisteners

  1. 导入需要的模块
  2. init() 中注册模块
  3. h() 函数的第二个参数处使用模块

Snabbdom 的核心

  1. init() 设置模块,创建 patch() 函数
  2. 使用 h() 函数创建 JavaScript 对象(VNode)描述真实 DOM
  3. patch() 比较新旧两个 Vnode
  4. 把变化的内容更新到真实 DOM 树

patch 整体过程分析

• patch(oldVnode, newVnode)
• 把新节点中变化的内容渲染到真实 DOM,最后返回新节点作为下一次 处理的旧节点
• 对比新旧 VNode 是否相同节点(节点的 key 和 sel 相同)
• 如果不是相同节点,删除之前的内容,重新渲染
• 如果是相同节点,再判断新的 VNode 是否有 text,如果有并且和 oldVnode 的 text 不同,直接更新文本内容
• 如果新的 VNode 有 children,判断子节点是否有变化

Diff 算法

Snbbdom 根据 DOM 的特点对传统的diff算法做了优化
• DOM 操作时候很少会跨级别操作节点
• 只比较同级别的节点


执行过程

在对开始和结束节点比较的时候,总共有四种情况
• oldStartVnode / newStartVnode (旧开始节点 / 新开始节点)
• oldEndVnode / newEndVnode (旧结束节点 / 新结束节点)
• oldStartVnode / newEndVnode (旧开始节点 / 新结束节点)
• oldEndVnode / newStartVnode (旧结束节点 / 新开始节点)


开始和结束节点

如果新旧开始节点是 sameVnode (key 和 sel 相同)
• 调用 patchVnode() 对比和更新节点
• 把旧开始和新开始索引往后移动 oldStartIdx++ / newStartIdx++


旧开始节点 / 新结束节点

• 调用 patchVnode() 对比和更新节点
• 把 oldStartVnode 对应的 DOM 元素,移动到右边,更新索引
为什么要移动到右边?

旧结束节点 / 新开始节点

• 调用 patchVnode() 对比和更新节点
• 把 oldEndVnode 对应的 DOM 元素,移动到左边,更新索引
为什么要移动到左边?

非上述四种情况
  1. 遍历新节点,使用 newStartNode 的 key 在老节点数组中找相同节点
  2. 如果没有找到,说明 newStartNode 是新节点
    • 创建新节点对应的 DOM 元素,插入到 DOM 树中
  3. 如果找到了
    • 判断新节点和找到的老节点的 sel 选择器是否相同
    • 如果不相同,说明节点被修改了
    重新创建对应的 DOM 元素,插入到 DOM 树中
    • 如果相同,把 elmToMove 对应的 DOM 元素,移动到左边


循环结束

• 当老节点的所有子节点先遍历完 (oldStartIdx > oldEndIdx),循环结束
• 新节点的所有子节点先遍历完 (newStartIdx > newEndIdx),循环结束

  1. oldStartIdx > oldEndIdx
    如果老节点的数组先遍历完(oldStartIdx > oldEndIdx)
    • 说明新节点有剩余,把剩余节点批量插入到右边


  2. newStartIdx > newEndIdx
    如果新节点的数组先遍历完(newStartIdx > newEndIdx)
    • 说明老节点有剩余,把剩余节点批量删除


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

推荐阅读更多精彩内容