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

相关推荐
望获linux15 小时前
【Linux基础知识系列:第一百五十九篇】磁盘健康监测:smartctl
linux·前端·数据库·chrome·python·操作系统·软件
十一吖i16 小时前
vue3表格显示隐藏列全屏拖动功能
前端·javascript·vue.js
冰暮流星17 小时前
css之线性渐变
前端·css
徐同保17 小时前
tailwindcss暗色主题切换
开发语言·前端·javascript
mapbar_front17 小时前
大厂精英为何在中小公司水土不服?
前端
生莫甲鲁浪戴18 小时前
Android Studio新手开发第二十七天
前端·javascript·android studio
2501_9160088920 小时前
Web 前端开发常用工具推荐与团队实践分享
android·前端·ios·小程序·uni-app·iphone·webview
SkylerHu21 小时前
前端代码规范:husky+ lint-staged+pre-commit
前端·代码规范
菜鸟una21 小时前
【微信小程序 + 消息订阅 + 授权】 微信小程序实现消息订阅流程介绍,代码示例(仅前端)
前端·vue.js·微信小程序·小程序·typescript·taro·1024程序员节
Yeats_Liao21 小时前
Go Web 编程快速入门 05 - 表单处理:urlencoded 与 multipart
前端·golang·iphone