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++
        }
      }
    }
相关推荐
openKaka_6 小时前
beginWork 的第一站:HostRoot 如何把 App 接入 Fiber 树
前端·javascript·react.js
Asa121386 小时前
Nature Microbiology|跨微生物界菌株水平传播推断的新算法TRACS
算法
叼烟扛炮7 小时前
C++ 知识点22 函数模板
开发语言·c++·算法·函数模版
Tisfy7 小时前
LeetCode 2553.分割数组中数字的数位:模拟(maybe+翻转)——java也O(1)
java·数学·算法·leetcode·题解·模拟·取模
平行侠7 小时前
33水库抽样 - 从未知大小的流中等概率采样
数据结构·算法
YOU OU7 小时前
HTML+CSS+JavaScript
前端·javascript·css·html
吴声子夜歌7 小时前
Java——Integer与二进制算法
java·算法
Controller-Inversion7 小时前
42. 接雨水
数据结构·算法·leetcode
Controller-Inversion7 小时前
33. 搜索旋转排序数组
数据结构·算法·leetcode
陆水A7 小时前
运输时效预测模型:静态路由时效的计算与验证
大数据·人工智能·算法·spark·数据库开发·etl工程师