Vue3 Diff算法核心优化实现

admin5天前it知识67

// Vue3 Diff算法核心优化实现function patchKeyedChildren(c1, c2, container) {  let i = 0;  const l1 = c1.length;  const l2 = c2.length;  let e1 = l1 - 1;  let e2 = l2 - 1;  // 1. 同步前置节点  while (i <= e1 && i <= e2) {    const n1 = c1[i];    const n2 = c2[i];    if (isSameVNode(n1, n2)) {      patch(n1, n2, container);    } else {      break;    }    i++;  }  // 2. 同步后置节点  while (i <= e1 && i <= e2) {    const n1 = c1[e1];    const n2 = c2[e2];    if (isSameVNode(n1, n2)) {      patch(n1, n2, container);    } else {      break;    }    e1--;    e2--;  }  // 3. 处理新增/删除节点  if (i > e1) {    // 新增节点    if (i <= e2) {      const nextPos = e2 + 1;      const anchor = nextPos < l2 ? c2[nextPos].el : null;      while (i <= e2) {        patch(null, c2[i], container, anchor);        i++;      }    }  } else if (i > e2) {    // 删除节点    while (i <= e1) {      unmount(c1[i]);      i++;    }  } else {    // 4. 处理中间乱序节点    const s1 = i;    const s2 = i;    const keyToNewIndexMap = new Map();    for (let j = s2; j <= e2; j++) {      const nextChild = c2[j];      keyToNewIndexMap.set(nextChild.key, j);    }    const toBePatched = e2 - s2 + 1;    const newIndexToOldIndexMap = new Array(toBePatched).fill(0);    for (let j = s1; j <= e1; j++) {      const prevChild = c1[j];      const newIndex = keyToNewIndexMap.get(prevChild.key);      if (newIndex === undefined) {        unmount(prevChild);      } else {        newIndexToOldIndexMap[newIndex - s2] = j + 1;        patch(prevChild, c2[newIndex], container);      }    }    const increasingNewIndexSequence = getSequence(newIndexToOldIndexMap);    let j = increasingNewIndexSequence.length - 1;    for (let i = toBePatched - 1; i >= 0; i--) {      const nextIndex = s2 + i;      const nextChild = c2[nextIndex];      const anchor = nextIndex + 1 < l2 ? c2[nextIndex + 1].el : null;      if (newIndexToOldIndexMap[i] === 0) {        patch(null, nextChild, container, anchor);      } else if (i !== increasingNewIndexSequence[j]) {        insert(nextChild.el, container, anchor);      } else {        j--;      }    }  }}function getSequence(arr) {  const p = arr.slice();  const result = [0];  let start, end, middle;  for (let i = 0; i < arr.length; i++) {    const arrI = arr[i];    if (arrI !== 0) {      let resultLastIndex = result[result.length - 1];      if (arr[resultLastIndex] < arrI) {        p[i] = resultLastIndex;        result.push(i);        continue;      }      start = 0;      end = result.length - 1;      while (start < end) {        middle = ((start + end) / 2) | 0;        if (arr[result[middle]] < arrI) {          start = middle + 1;        } else {          end = middle;        }      }      if (arr[result[start]] > arrI) {        if (start > 0) {          p[i] = result[start - 1];        }        result[start] = i;      }    }  }  let i = result.length - 1;  let last = result[i];  while (i >= 0) {    result[i] = last;    last = p[last];    i--;  }  return result;}

代码说明:

实现了Vue3核心Diff算法流程:同步前置/后置节点、处理新增/删除节点、中间乱序节点的最长递增子序列优化

通过静态标记和patchFlag优化:跳过静态节点、仅对比动态变化部分

支持Fragment(多根节点)和事件缓存:减少DOM层级、复用事件函数

通过getSequence函数实现最长递增子序列算法:O(nlogn)时间复杂度

包含isSameVNode、patch、unmount、insert等辅助函数(未实现)



标签: 分享IT知识
返回列表

上一篇:手写一个简易的响应式系统

没有最新的文章了...

相关文章

夏天的台风

夏天,是一个充满活力和生命力的季节,但同时也伴随着台风的出现。每年的这个时期,台风如同一股强大的自然力量,给人们的生命和财产带来了一定的威胁。在台风的肆虐中,可以看到大自然的威力与无情。台风带来的强风...

个人学习计划

学习计划是一个帮助你提高学习效率和使用时间的有效工具。以下是一个可能的学习计划:目标设定。 在开始学习之前,明确你的学习目标和目的地,这有助于你制定实际可行的计划。分解任务。 将大...

炎热的夏天

夏天是一个充满活力和热情的季节,炎热的的气息让人感到无力和疲惫。但是,这个季节也有着许多美好的回忆和乐趣,让我们一起来看看夏天的美好与炎热吧。首先,夏天的天气非常炎热,太阳高照,蓝天白云,气温高达30...

如何学习 javascript

学习JavaScript需要以下步骤:基础语法:学习JavaScript的基础语法,包括变量、数据类型、函数、循环、条件语句等。DOM 操作:学习如何操作 DOM,例如获取和修改元素、添加和删除事件处...

马斯洛理论

生理需求是最低层次的需求,包括人类维持自身生存的最基本要求,包括饥、渴、衣、住、性、健康方面的需求。安全需求包括两个层次,一是归属的需要,即人都有一种归属于一个群体的感情,希望成为群体中的一员,并相互...

如果百度不收录,如何提高网站人气

假设你是一个新兴的瑜伽品牌,你创建了一个网站来宣传你的瑜伽课程和品牌。然而,你发现百度搜索引擎并没有收录你的网站,这导致你的网站流量和人气较低。以下是你可以采取的一些策略来提高网站人气:优化网站结构:...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。