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++
        }
      }
    }
相关推荐
三块可乐两块冰1 小时前
【第二十六周】机器学习笔记二十七
算法·机器学习·支持向量机
汝生淮南吾在北2 小时前
SpringBoot3+Vue3个人健康管理网站
vue.js·spring boot·毕业设计·毕设
源代码•宸2 小时前
大厂技术岗面试之一面(准备自我介绍、反问)
经验分享·后端·算法·面试·职场和发展·golang·反问
s09071362 小时前
FPGA视频编码器:H.264/H.265实现核心技术解析
图像处理·算法·fpga开发·音视频·h.264
靓仔建2 小时前
用tdesign-vue-next的t-tree-select做个下拉单选框
javascript·vue.js·tdesign
闪电麦坤953 小时前
Leecode热题100:缺失的第一个正数(数组)
数据结构·算法·leetcode
梨子串桃子_10 小时前
推荐系统学习笔记 | PyTorch学习笔记
pytorch·笔记·python·学习·算法
夏鹏今天学习了吗10 小时前
【LeetCode热题100(83/100)】最长递增子序列
算法·leetcode·职场和发展
情缘晓梦.10 小时前
C语言指针进阶
java·开发语言·算法