Vue.js 设计与实现
霍春阳(HcySunYang)
Vue.js 官方团队成员
340 人已学习
立即订阅
Vue.js 设计与实现
15
15
1.0x
00:00/00:00
登录|注册

第 9 章 简单 Diff 算法

从本章开始,我们将介绍渲染器的核心 Diff 算法。简单来说,当新旧 vnode 的子节点都是一组节点时,为了以最小的性能开销完成更新操作,需要比较两组子节点,用于比较的算法就叫作 Diff 算法。我们知道,操作 DOM 的性能开销通常比较大,而渲染器的核心 Diff 算法就是为了解决这个问题而诞生的。

9.1 减少 DOM 操作的性能开销

核心 Diff 只关心新旧虚拟节点都存在一组子节点的情况。在上一章中,我们针对两组子节点的更新,采用了一种简单直接的手段,即卸载全部旧子节点,再挂载全部新子节点。这么做的确可以完成更新,但由于没有复用任何 DOM 元素,所以会产生极大的性能开销。
以下面的新旧虚拟节点为例:
// 旧 vnode
const oldVNode = {
type: 'div',
children: [
{ type: 'p', children: '1' },
{ type: 'p', children: '2' },
{ type: 'p', children: '3' }
]
}
// 新 vnode
const newVNode = {
type: ‘div’,
children: [
{ type: ‘p’, children: ‘4’ },
{ type: ‘p’, children: ‘5’ },
{ type: ‘p’, children: ‘6’ }
]
}
按照之前的做法,当更新子节点时,我们需要执行 6 次 DOM 操作:
卸载所有旧子节点,需要 3 次 DOM 删除操作;
挂载所有新子节点,需要 3 次 DOM 添加操作。
但是,通过观察上面新旧 vnode 的子节点,可以发现:
更新前后的所有子节点都是 p 标签,即标签元素不变;
只有 p 标签的子节点(文本节点)会发生变化。
例如,oldVNode 的第一个子节点是一个 p 标签,且该 p 标签的子节点类型是文本节点,内容是 '1'。而 newVNode 的第一个子节点也是一个 p 标签,它的子节点的类型也是文本节点,内容是 '4'。可以发现,更新前后改变的只有 p 标签文本节点的内容。所以,最理想的更新方式是,直接更新这个 p 标签的文本节点的内容。这样只需要一次 DOM 操作,即可完成一个 p 标签更新。新旧虚拟节点都有 3 个 p 标签作为子节点,所以一共只需要 3 次 DOM 操作就可以完成全部节点的更新。相比原来需要执行 6 次 DOM 操作才能完成更新的方式,其性能提升了一倍。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了渲染器核心 Diff 算法,旨在解决更新操作中的性能开销问题。首先,通过比较新旧虚拟节点的子节点,提出了一种更新方式,即只更新发生变化的部分,从而减少了 DOM 操作次数,提升了性能。随后,作者指出了该方法存在的问题,并提出了遍历长度较短的一组子节点,并根据新旧两组子节点的长度关系进行挂载或卸载的优化方案。进一步讨论了 DOM 复用与 key 的作用,提出了通过 DOM 的移动来完成子节点的更新,以减少不必要的 DOM 操作。通过介绍简单直接的 Diff 算法,以及对其进行优化的思路,为读者提供了一种有效提升渲染性能的方法。总体来说,本文内容涉及了虚拟节点的比较、DOM 操作的优化以及节点复用等技术特点,对于想要提升渲染性能的开发者来说,是一篇值得阅读的技术文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Vue.js 设计与实现》
立即购买
登录 后留言

精选留言

由作者筛选后的优质留言将会公开显示,欢迎踊跃留言。
收起评论
显示
设置
留言
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部