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 所占用的内存空间则会被垃圾回收。

相关推荐
SquabbyZhu12 分钟前
从 4 个 URL 到 1 个入口:Peaks-Loop 驱动的微前端聚合实践
前端
Hilaku21 分钟前
技术好就能升职是前端圈最大的谎言!
前端·javascript·程序员
lhldsg23 分钟前
树洞倾诉的核心需求与产品定位误区
java·前端·小程序
光影少年35 分钟前
react navite高频手写/实操题
前端·javascript·react native·react.js·前端框架
hunterandroid1 小时前
HarmonyOS 弱网与离线优先架构实战:请求队列、本地缓存与增量同步
前端·前端框架
lhldsg1 小时前
宠物同城领养平台开发实战:从需求分析到上线部署指南
java·前端·小程序·需求分析·宠物
hunterandroid1 小时前
Android 内存泄漏排查实战:从 LeakCanary 报警到根因定位
android·前端
leoZ2311 小时前
AI+前端提效-12 AI辅助前端性能优化与监控:从开发到线上全流程提效
前端·人工智能·神经网络·自然语言处理·性能优化·keras·知识图谱
阿图灵1 小时前
LangGraph 实战 03:Workflows 与 Agents——六种工作流模式与智能体实战(附 6 个可运行示例)
java·前端·javascript·工作流·ai agent·智能体·langgraph
狂炫冰美式1 小时前
电脑合盖之后 Cursor 还在偷我电?看看为啥
前端·人工智能·后端