Vue2 的 diff 算法原理

diff 的时机

当组件创建、以及依赖的属性或数据变化从而运行_update()函数时。

_update 的作用

  1. 接收一个vnode参数,即新的 vnode。
  2. 同时通过当前组件的_vnode属性拿到旧的 vnode。
  3. 将新的 vnode 赋值给 _vnode 属性。
  4. 判断旧的 vnode 是否存在:
    • 不存在则调用patch函数遍历新的 vnode 为每个节点创建真实 DOM,并挂载到每个节点的ele属性上。
    • 存在则通过 patch 函数对新旧 vnode 进行对比,让新 vnode 的每个节点的 ele 属性匹配到合适的真实 DOM,并以最小代价完成真实 DOM 处理。

patch 函数的运行流程

主要是通过同时满足以下 3 个条件判断两个虚拟节点是否相同(相同三要素):

  1. 标签类型tag是否相同
  2. key值是否相同
  3. 如果是 input 元素, type 属性是否相同

对比过程总结为深度优先,同层对比,即先将当前节点及其子节点对比完,再从同层节点寻找下个对比对象,详细流程:

  1. 根节点比较

    • 若相同,则开始更新,将旧节点的真实 dom 赋值给新节点的 ele 属性,对比新旧节点的属性,将变化更新到真实 dom 中,当前两个节点处理完毕后开始对比子节点。
    • 若不相同,则新节点递归创建真实 dom,旧节点销毁 ele 属性,即销毁旧的真实 dom。
  2. 对比子节点,大致与上述对比相同,通过以下方面进行对比效率提升

    • 优先只改动真实 dom 元素属性
    • 其次移动元素以替代创建和删除元素
    • 最后才考虑创建和删除元素

子节点对比细节

vue 对新旧 vnode 生成了新旧两个子节点数组,并对两个数组同使用两个指针,分别指向各自数组的头和尾,然后不断向数组中间靠拢来一一对比:

若新旧数组的头或尾指针所指向的节点相同(相同三要素),则只改动真实 dom 元素的属性差异,同时当前两个指针移动。

若不同则从旧数组中寻找所有与当前新数组头指针相同的节点,若还没找到,则创建元素,同时新数组头或尾指针移动,进行下一轮对比...当新数组头指针超过尾指针,循环结束,没有被匹配到的旧数组会被遍历删除元素。

就这样一直递归遍历下去,直到整颗新的 vnode tree 对比完成,之后旧的 vnode 所占用的内存空间则会被垃圾回收。

相关推荐
Mintopia3 分钟前
🎯 光与面的命运交锋:Möller-Trumbore 线段三角形相交算法全解析
前端·javascript·计算机图形学
Ares-Wang10 分钟前
Vue》》@ 用法
前端·javascript·vue.js
心.c44 分钟前
JavaScript单线程实现异步
开发语言·前端·javascript·ecmascript
爱分享的程序员1 小时前
前端面试专栏-前沿技术:31.Serverless与云原生开发
前端·javascript·面试
姜 萌@cnblogs2 小时前
Saga Reader 0.9.9 版本亮点:深入解析核心新功能实现
前端·ai·rust
gnip2 小时前
实现elementplus官网主题切换特效
前端·css
Darling02zjh2 小时前
HTML5
前端·html·html5
成长ing121382 小时前
闪白效果
前端·cocos creator
Lazy_zheng2 小时前
React架构深度解析:从 Stack 到 Fiber,解决 CPU 和 I/O 瓶颈问题
前端·react.js·前端框架
张元清2 小时前
什么是React并发模式中的Tearing(撕裂)
前端·面试