diff算法

1 篇文章 0 订阅
1 篇文章 0 订阅

在了解diff算法前,我们需要想了解一下什么是虚拟DOM,diff算法为什么可以提升代码效率?

一、什么是虚拟DOM

虚拟DOM是一个对象,一个什么样的对象呢?一个用来表示真实DOM的对象。我举个例子,请看以下真实DOM

  <!-- 真实DOM -->
    <ul id="list">
      <li class="item">桃子</li>
      <li class="item">苹果</li>
      <li class="item">西瓜</li>
    </ul>

生成一个虚拟DOM:

    <!-- 虚拟DOM:对象的形式描述真实DOM -->
    let oldVDOM = {
      tagName: 'ul', // 头标签名
      props: {  // 头标签的属性
        id: 'list'
      }
      children: [  // 标签的子节点,上面真实DOM的子节点有三个
        {
          // 对子节点进行描述
          tagName: 'li', progs: { class: 'item'}, children: '桃子'
        },
        {
          tagName: 'li', progs: { class: 'item'}, children: '苹果'
        },
        {
          tagName: 'li', progs: { class: 'item'}, children: '西瓜'
        }
      ]
    }

在修改一个li标签的文本时,生成一个新虚拟DOM,来表示真实的修改后的DOM

  
     let newVDOM = {
      tagName: 'ul', // 头标签名
      props: {  // 头标签的属性
        id: 'list'
      }
      children: [  // 标签的子节点,上面真实DOM的子节点有三个
        {
          // 对子节点进行描述
          tagName: 'li', progs: { class: 'item'}, children: '桃子'
        },
        {
          tagName: 'li', progs: { class: 'item'}, children: '西瓜'
        },
        {
          tagName: 'li', progs: { class: 'item'}, children: '苹果'
        },
        {
          tagName: 'li', progs: { class: 'item'}, children: '草莓'
        }
      ]
    }

这就是我们的新旧虚拟DOM,在我们修改li时,有两种渲染列表的方法,

①直接渲染

②使用虚拟DOM

虚拟DOM算法操作真实DOM,性能高于直接操作真实DOM。

虚拟DOM虚拟DOM算法是两种概念。虚拟DOM算法 = 虚拟DOM + Diff算法


二、什么是Diff算法

Diff算法是一种对比算法。对比两者是旧虚拟DOM和新虚拟DOM,对比出是哪个虚拟节点更改了,找出这个虚拟节点,并只更新这个虚拟节点所对应的真实节点,而不用更新其他数据没发生改变的节点,实现精准地更新真实DOM,进而提高效率


三、Diff算法的原理:

①Diff同层对比

新旧虚拟DOM对比的时候,Diff算法比较只会在同层级进行, 不会跨层级比较。 所以Diff算法是:广度优先算法。 时间复杂度:O(n)

②比较的东西

新旧虚拟DOM对比的时候,首先比较的key

③新旧DOM比较


那么新旧两个子节点集合以及其首尾指针为:

 然后会进行互相进行比较,总共有五种比较情况:

1、oldS 和 newS 使用sameVnode方法进行比较,sameVnode(oldS, newS)

2、oldS 和 newE 使用sameVnode方法进行比较,sameVnode(oldS, newE)

3、oldE 和 newS 使用sameVnode方法进行比较,sameVnode(oldE, newS)

4、oldE 和 newE 使用sameVnode方法进行比较,sameVnode(oldE, newE)

5、如果以上逻辑都匹配不到,再把所有旧子节点的 key 做一个映射到旧节点下标的 key -> index 表,然后用新 vnode 的 key 去找出在旧节点中可以复用的位置。

具体步骤:

第一步:olds 和 news 比较

 第二步:olds++ 指针指向苹果 news ++ 指针指向 西瓜  

 后面是相同的比较方法

 

注意: (在我们渲染列表的时候,需要绑定key.)

绑定key我们第一时间肯定会想让我们的索引成为key,但是这是错误的

我们在比较新旧虚拟DOM的时候,第一步比较的就是他们的key值,如果使用索引充当key的话。没有我们想着的,复用已有节点,局部渲染不同节点或新增节点等。

所以,我们key需要使用唯一确定的值,去充当key值。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值