什么是虚拟DOM 链接到标题
一个用来表示真实DOM的对象
<ul id="list">
<li class="item">哈哈</li>
<li class="item">呵呵</li>
<li class="item">嘿嘿</li>
</ul>
let oldVDOM = { // 旧虚拟DOM
tagName: 'ul', // 标签名
props: { // 标签属性
id: 'list'
},
children: [ // 标签子节点
{
tagName: 'li', props: { class: 'item' }, children: ['哈哈']
},
{
tagName: 'li', props: { class: 'item' }, children: ['呵呵']
},
{
tagName: 'li', props: { class: 'item' }, children: ['嘿嘿']
},
]
}
虚拟DOM算法操作真实DOM,性能高于直接操作真实DOM
什么是diff算法 —- vue2 链接到标题
diff 算法是一种通过同层的树节点进行比较的高效算法,深度优先算法。 时间复杂度:O(n)
其有两个特点:
•比较只会在同层级进行, 不会跨层级比较
•在diff比较的过程中,循环从两边向中间比较
流程:
当数据改变时,会触发setter,并且通过Dep.notify去通知所有订阅者Watcher,订阅者们就会调用patch方法,给真实DOM打补丁,更新相应的视图。
分为多种情况:
patch方法:接收两个参数,oldVnode newVnode
如果 这俩相同(判断标注:key、标签名、input框要求type相同、是否都有data),那么继续向深层比较
如果这两个对象 === 比完一样,那么终止
如果节点类型一样,但是内容不一样,则用newVnode 里面的替换掉 旧的
他们的孩子处理 : 多了添加,少了删除,如果都有孩子,那么就要进行 updateChildren
如果这俩不相同,替换就行了
const oldEl = oldVnode.el; //旧虚拟节点的真实DOM节点 ,为了拿到他的父节点
const parentEl = api.parentNode(oldEl) // 拿到原本的父节点
createEl(newVnode); //创建新虚拟节点对应 的真实dom
if(parentEl!==null) {
api.insertBefore(parentEle, vnode.el, api.nextSibling(oEl)) // 将新元素添加进父元素
api.removeChild(parentEle, oldVnode.el) // 移除以前的旧元素节点
oldVnode = null
}
return newVnode
updateChildren 链接到标题
对比的方法就是首尾指针法:
新的子节点集合和旧的子节点集合,各有首尾两个指针
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
修改数据后
<ul>
<li>b</li>
<li>c</li>
<li>e</li>
<li>a</li>
</ul>

然后会进行互相进行比较,总共有五种比较情况:
oldS = a, oldE = c
newS = b, newE = a
- 1、
oldS 和 newS使用sameVnode方法进行比较,sameVnode(oldS, newS) - 2、
oldS 和 newE使用sameVnode方法进行比较,sameVnode(oldS, newE) - 3、
oldE 和 newS使用sameVnode方法进行比较,sameVnode(oldE, newS) - 4、
oldE 和 newE使用sameVnode方法进行比较,sameVnode(oldE, newE) - 5、如果以上逻辑都匹配不到,再把所有旧子节点的
key做一个映射到旧节点下标的key -> index表,然后用新vnode的key去找出在旧节点中可以复用的位置。
第一步 链接到标题
oldS 和 newE 相等,需要把节点a移动到newE所对应的位置

此时 oldS和 newE 移动 【只让相等的移动。S++ E–】
第二步 链接到标题

第三步 链接到标题

第四步 链接到标题
oldS > oldE,则oldCh先遍历完成了,而newCh还没遍历完,说明newCh比oldCh多,所以需要将多出来的节点,插入到真实DOM上对应的位置上

Vue3 Diff —— 最长递增子序列 链接到标题
静态标记(PatchFlags):编译阶段标记动态内容,diff 时只处理动态部分,跳过静态节点;
最长递增子序列:针对列表渲染,计算最小 DOM 移动量,减少不必要的 DOM 操作;
非递归流程:避免深层递归阻塞主线程,配合浏览器调度更流畅。
这是 Vue3 diff 最核心的部分,针对 v-for 列表的对比逻辑:
- 步骤 1:先做「头尾快速对比」(比如旧列表头是 a,新列表头也是 a → 直接复用,指针后移);
- 步骤 2:对剩余节点,用「最长递增子序列」计算出无需移动的节点;
- 步骤 3:只移动需要调整位置的节点,或创建 / 删除新增 / 删除的节点。