当前位置: 首页> 科技> IT业 > Vue中的diff算法

Vue中的diff算法

时间:2025/7/17 14:43:39来源:https://blog.csdn.net/fmk1023/article/details/140610532 浏览次数:0次

文章目录

  • diff算法是什么
  • 比较方式
  • 源码分析
    • patch
    • patchVnode
    • updateChildren
    • 小结
  • Vue3中diff算法优化

diff算法是什么

diff算法是一种通过同层的树节点进行比较的高效算法

其有两个特点:

  • 比较只会在同层级进行,不会跨层级比较
  • 在dff比较的过程中,循环从两边向中间比较(首位交叉对比

diff算法在很多场景下都有应用,在Vue中,作用于虚拟dom渲染成真实dom的新旧VNode节点比较

比较方式

diff整体策略为:深度优先,同层比较

  1. 比较只会在同层级进行,不会跨层级比较
    在这里插入图片描述
  2. 比较的过程中,循环从两边向中间收拢
    在这里插入图片描述
    下面举个vue通过diff算法更新的例子:
    新旧VNode节点如下图所示:
    在这里插入图片描述
    第一次循环后,发现旧节点D与新节点D相同,直接复用引旧节点D作为diff后的第一个真实节点,同时旧节点endIndex移动到C,新节点的startIndex移动到了C
    在这里插入图片描述
    第二次循环后,同样是旧节点的末尾和新节点的开头(都是C)相同,同理,diff后创建了C的真实节点插入到第一次创建的D节点后面。同时旧节点的endIndex移动到了B,新节点的startIndex移动到了E
    在这里插入图片描述
    第三次循环中,发现E没有找到,这时候只能直接创建新的真实节点E,插入到第二次创建的C节点之后。同时新节点的startIndex移动到了A。旧节点的startIndex和endIndex都保持不动。
    在这里插入图片描述

源码分析

当数据发生改变时,set方法会调用Dep.notify通知所有订阅者Watcher,订阅者就会调用patch给真实的DOM打补丁,更新相应的视图
源码位置:src/core/vdom/patch.js

patch

function patch(oldVnode, vnode, hydrating, removeOnly) {if (isUndef(vnode)) { // destoryif (isDef(oldVnode)) invokeDestroyHook(oldVnode)return}let isInitialPatch = falseconst insertedVnodeQueue = []if (isUndef(oldVnode)) {isInitialPatch = truecreateElm(vnode, insertedVnodeQueue) // dom} else {const isRealElement = isDef(oldVnode.nodeType)if (!isRealElement && sameVnode(oldVnode, vnode)) {// patchVnodepatchVnode(oldVnode, vnode, insertedVnodeQueue, null, null, removeOnly)} else {// domif (isRealElement) {if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {oldVnode.removeAttribute(SSR_ATTR)hydrating = true}if (isTrue(hydrating)) {if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {invokeInsertHook(vnode, insertedVnodeQueue, true)return oldVnode}}oldVnode = emptyNodeAt(oldVnode)}return vnode.elm}}
}

patch函数前两个参数位为oldVnodeVnode,分别代表新的节点和之前的旧节点,主要做了四个判断:

  • 没有新节点,直接触发旧节点的destory钩子
  • 没有旧节点,说明是页面刚开始初始化的时候,此时,根本不需要比较了,直接全是新建,所以只调用createElm
  • 旧节点和新节点自身一样,通过sameVnode判断节点是否一样,一样时,直接调用patchVnode去处理这两个节点
  • 旧节点和新节点自身不一样,当两个节点不一样的时候,直接创建新节点,删除旧节点

patchVnode

function patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly) {// 如果新旧节点一致,什么都不做if (oldVnode === vnode) {return
关键字:Vue中的diff算法

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: