列表

详情


62. 说一下Diff算法?

回答思路

得分点 patch、patchVnode、updateChildren、vue优化时间复杂度为O(n) 标准回答 Diff算法比较过程 第一步:patch函数中对新老节点进行比较 如果新节点不存在就销毁老节点 如果老节点不存在,直接创建新的节点 当两个节点是相同节点的时候,进入 patctVnode 的过程,比较两个节点的内部 第二步:patchVnode函数比较两个虚拟节点内部 如果两个虚拟节点完全相同,返回 当前vnode 的children 不是textNode,再分成三种情况 - 有新children,没有旧children,创建新的 - 没有新children,有旧children,删除旧的 - 新children、旧children都有,执行`updateChildren`比较children的差异,这里就是diff算法的核心 当前vnode 的children 是textNode,直接更新text 第三步:updateChildren函数子节点进行比较 - 第一步 头头比较。若相似,旧头新头指针后移(即 `oldStartIdx++` && `newStartIdx++`),真实dom不变,进入下一次循环;不相似,进入第二步。 - 第二步 尾尾比较。若相似,旧尾新尾指针前移(即 `oldEndIdx--` && `newEndIdx--`),真实dom不变,进入下一次循环;不相似,进入第三步。 - 第三步 头尾比较。若相似,旧头指针后移,新尾指针前移(即 `oldStartIdx++` && `newEndIdx--`),未确认dom序列中的头移到尾,进入下一次循环;不相似,进入第四步。 - 第四步 尾头比较。若相似,旧尾指针前移,新头指针后移(即 `oldEndIdx--` && `newStartIdx++`),未确认dom序列中的尾移到头,进入下一次循环;不相似,进入第五步。 - 第五步 若节点有key且在旧子节点数组中找到sameVnode(tag和key都一致),则将其dom移动到当前真实dom序列的头部,新头指针后移(即 `newStartIdx++`);否则,vnode对应的dom(`vnode[newStartIdx].elm`)插入当前真实dom序列的头部,新头指针后移(即 `newStartIdx++`)。 - 但结束循环后,有两种情况需要考虑: - 新的字节点数组(newCh)被遍历完(`newStartIdx > newEndIdx`)。那就需要把多余的旧dom(`oldStartIdx -> oldEndIdx`)都删除,上述例子中就是`c,d`; - 新的字节点数组(oldCh)被遍历完(`oldStartIdx > oldEndIdx`)。那就需要把多余的新dom(`newStartIdx -> newEndIdx`)都添加。

上一题