33-mini-vue 更新element的children-双端对比diff算法

更新element的children-双端对比diff算法

  1. 中间对比

  2. 案例

    • a b ( c y e ) f g < -------- >
    • a b ( e d c ) f g
  3. 情况分析

    • 创建新的(d) (在老的里面不存在,新的里面存在)
    • 删除老的(y) (在老的里面存在,新的里面不存在)
    • 移动(c,e) (节点存在于新的和老的里面,但是位置变了)
  4. 针对相应的情况进行实现功能

    1. 老节点里面有,新节点里面无 如何进行判断呢
      • 遍历新节点进行查找是否存在老节点,我们使用双端对比,减少了O(n) 里面的 n
      • 直接使用 key来进行判断,时间空间复杂度属于 O(1)
    2. 测试案例
    js 复制代码
    // 5.1 
    // a b ( c d ) f g
    // a b ( e c ) f g
    // d 节点在新的里面是没有的 - 需要删除掉
    // c 节点 props 也发生了变化
    const prevChldren = [
      h('p', { key: 'A'}, "A"),
      h('p', { key: 'B'}, "B"),
      h('p', { key: 'C', id: 'c-prev'}, "C"),
      h('p', { key: 'D'}, "D"),
      h('p', { key: 'F'}, "F"),
      h('p', { key: 'G'}, "G"),
    ]
    const nextChildren = [
      h('p', { key: 'A'},'A'),
      h('p', { key: 'B'},'B'),
      h('p', { key: 'E'},'E'),
      h('p', { key: 'C', id: 'c-next'},'C'),
      h('p', { key: 'F'},'F'),
      h('p', { key: 'G'},'G')
    ]
  5. 实现过程

    1. 观察我们发现上面的测试案例, prevChildren 与 nextChildren ,我们先研究的点是

      • 新的里面没有D,进行删除
      • 新的里面 C 的 id 属性值不同,进行修改
    2. 功能实现

    js 复制代码
    // 新的比老的多
    if (i > e1) {
      if (i <= e2) {
        const nextPos = i + 1
        const anchor = nextPos < l2 ? c2[nextPos].el : null
        while (i <= e2) {
          patch(null, c2[i], container, parentComponent, anchor)
          i++
        }
      }
      // 老的比新的多
    } else if (i > e2) {
      while (i <= e1) {
        hostPatchRemove(c1[i].el)
        i++
      }
    } else {
      // ✅ 中间对比
      let s1 = i
      let s2 = i
      let toBePatched = e2 - s2 + 1 // ✅ 优化
      let patched = 0 // ✅ 优化
      const keyToNewIndexMap = new Map()
    
      for (let i = s2; i <= e2; i++) { // 将新节点的每个元素的 key 存入 map
        const nextChild = c2[i]
        keyToNewIndexMap.set(nextChild.key, i)
      }
    
      for (let i = s1; i <= e1; i++) {
        const prevChild = c1[i]
        if (patched >= toBePatched) { // ✅ 优化
          hostPatchRemove(prevChild.el)
          continue;
        }
        // null,unfined
        let newIndex
        // ✅ 看老节点的 key 能不能和新节点匹配上
        if (prevChild.key != null) {
          newIndex = keyToNewIndexMap.get(prevChild.key)
        } else {
          for (let j = s2; j <= e2; j++) {
            if (isSameVNodeType(prevChild, c2[j])) {
              newIndex = j
              break
            }
          }
    
        }
        if (newIndex === undefined) { // ✅ 新节点里面没有,就把老节点删除
          hostPatchRemove(prevChild.el)
        } else { // ✅ 新节点里面有就进行对比渲染
          patch(prevChild, c2[newIndex], container, parentComponent, null)
          patched++
        }
      }
    }
相关推荐
小磊哥er2 分钟前
深入解构Claude Code - 第 6 篇 · 终端里的图形界面
javascript·ai编程
海兰4 分钟前
【应用】基于 Next.js 16 + Python mplfinance的金融K线图与技术指标可视化平台(一)
javascript·python·金融
吃好睡好便好1 小时前
查找函数的使用
学习·算法·matlab·生活·查找函数
学习星球1 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
可乐鸡翅yeah_1 小时前
hls.js 内存泄漏实战排查,直播 M3U8 长时间播放异常定位方案
开发语言·javascript·python·django·ecmascript·m3u8·m3u8在线
可乐鸡翅yeah_2 小时前
第三方接口对接 M3U8 流媒体排坑实战,解决外部服务商流兼容难题
前端·javascript·python·django·html·m3u8·m3u8在线
默_笙2 小时前
🏠 「LLM Notes」:我用 Next.js + Redis 给自己造了个笔记博客
前端·javascript
靠沿3 小时前
贪心算法专题(二)
算法·贪心算法
猎头南楼3 小时前
具身智能模型部署方向的能力要求与技术栈梳理
人工智能·深度学习·算法
ruanCat4 小时前
Prettier 明明执行成功,Markdown 为什么还是没变?一次插件误诊复盘
前端·javascript·node.js