虚拟 DOM 就是 js 对真实 DOM 的模拟,是一个对象
为什么要用虚拟 DOM
数据驱动视图,控制操作 DOM 次数
Vue 基于 Snabbdom 库 实现虚拟 DOM
虚拟 DOM 的好处
比较变化,计算最小需要更新的视图,然后在操作 DOM
- 减少直接操作DOM:传统 DOM 操作频繁触发回流/重绘,虚拟DOM 通过批量更新和局部渲染优化性能
- 状态追踪:数据变化时生成新虚拟DOM,通过 DIFF 算法对比新旧差异,仅更新必要部分。
diff 算法:通过一种同层的树节点进行比较的高效算法
1. 遍历老的虚拟 DOM
2. 遍历新的虚拟 DOM
3. 重新排序
两个特点:
- 只比较同一层级,不跨级比较
- 在 diff 比较的过程中,循环从两边向中间比较
只比较标签名,1. 标签名不同,直接删除,不继续深度比较; 2. 标签名相同,key 相同,就认为是相同节点,不继续深度比较;
原理分析:
- 当数据发生改变时,订阅者 watcher 就会调用 patch 给真实的 DOM 打补丁
- 通过 isSameVnode 进行判断,相同则调用 patchVnode 方法
- patchVnode 做了以下操作:
- 找到对应的真实 dom,称为 el
- 如果都有文本节点且不相等,将 el 文本节点设置为 Vnode 的文本节点
- 如果 oldVnode 有子节点而 VNode 没有,则删除 el 子节点
- 如果 oldVnode 没有子节点而 VNode 有,则将 VNode 的子节点真实化添加到 el
- 如果两者都有子节点,则执行 updateChildren 函数比较子节点
- updateChildren 主要做了以下操作
- 设置新旧 VNode 的头尾指针
- 新旧头尾指针进行比较,循环向中间靠拢,根据情况调用 patchVnode 进行 patch 重复流程、调用 createElem 创建一个新的节点,从哈希表中寻找 key 一致的 VNode 节点再分情况操作