diff
算法到底是什么?diff
算法是一种通过同层的树节点进行比较的高效算法,它可以不用频繁操作DOM
,而是选用虚拟DOM
节点操作,说人话就是专门用来处理虚拟DOM节点的。
为了更好理解Vue
的diff
算法,请先看一位B站大佬精心制作的
通过上面视频可以很好理解diff算法的比较流程,清楚在循环从左右两边向中间比较的更新、插入、删除、查询操作。
它的操作本质就是:
分别遍历新旧虚拟DOM
节点的数组,接着通过循环左右双指针比较判断。
新的头 newStartIndex 和老的头 oldStartIndex 对比
新的尾 newEndIndex 和老的尾 oldEndIndex 对比
新的头 newStartIndex 和老的尾 oldEndIndex 对比
新的尾 newEndIndex 和老的头 oldStartIndex 对比
我看到掘金的一篇讲的很不错,可以看看,深入浅出虚拟 DOM 和 Diff 算法,及 Vue2 与 Vue3 中的区别,我就只负责总结一下学习笔记吧。
而且它讲的Vue3涉及到diff的内容也很易理解。
在页面首次渲染的时候会调用一次 patch
并创建新的 vnode
,不会进行更深层次的比较。
setter
然后通过 Notify
通知 Watcher
。Watcher
会通知更新并执行更新函数,它会执行 render
函数获取新的虚拟 DOM
。patch
对比上次渲染结果的老的虚拟 DOM
,并计算出最小的变化,然后再去根据这个最小的变化去更新真实的 DOM
,也就是视图View
oldVnode
和 vnode
的引用地址是一样的,就表示节点没有变化,直接返回。oldVnode
的 isAsyncPlaceholder
判断注释、v-if
和异步函数的情况,选择跳过异步组件的检查,直接返回。oldVnode
和 vnode
都是静态节点,有相同的 key
vnode
是克隆节点或者 v-once
指令控制的节点时
oldVnode.elm
和 oldVnode.child
都复制到 vnode
上,然后返回。vnode
不是文本节点也不是注释的情况下:
vnode
文本为 undefined
,就删掉 vnode.elm
文本vnode
和 oldVnode
都有子节点,而且子节点不一样的话,就调用 updateChildren
更新子节点vnode
有子节点,就调用 addVnodes
创建子节点oldVnode
有子节点,就调用 removeVnodes
删除该子节点vnode
是文本节点但是和 oldVnode
文本内容不一样,就更新文本当每轮循环对比时都不能满足找到对应的key值与标签值一致的情况时,那么要不断拿 新的开始节点 的 key 去 老的开始节点的子节点 children 找。