diff算法

     为什么要有diff算法呢?因为在v-for渲染列表的时候,我们在更改数据的时候会进行整个列表的渲染,为了增加代码效率,我们只需要进行一个局部的渲染,所以我们要使用diff算法进行节点比对,进行局部渲染。

在我们了解diff算法前,我们需要知道什么是虚拟DOM

虚拟DOM :

虚拟DOM就是用来表示真实DOM的对象(通俗来讲就是以对象的形式去描述我们的真实DOM)

例子:

真实DOM:
<ul id="list">
​
    <li class="item">雪碧</li>
​
    <li class="item">可乐</li>
​
    <li class="item">芬达</li>
​
</ul>
对应的虚拟DOM为:
let oldVDOM = { // 旧虚拟DOM
​
        tagName: 'ul', // 标签名
​
        props: { // 标签属性
​
            id: 'list'
​
        },
​
        children: [ // 标签子节点
​
            {
​
                tagName: 'li', props: { class: 'item' }, children: ['雪碧']
​
            },
​
            {
​
                tagName: 'li', props: { class: 'item' }, children: ['可乐']
​
           },
​
           {
​
                tagName: 'li', props: { class: 'item' }, children: ['芬达']
​
            },
​
        ]
​
    }
 

当我们去修改真实DOM的时候,会产生一个新的虚拟DOM,而我们的diff算法就是新旧虚拟DOM的对比查看每个节点是否发生改变,如果改变那么就进行局部渲染 。

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

总共有五种比较情况:

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 表,然后用新 vnodekey 去找出在旧节点中可以复用的位置。

注 :这里的key不能使用索引哦!

第一步:

oldS = a, oldE = c 
newS = b, newE = a

比较结果:oldS 和 newE 相等,需要把节点a移动到newE所对应的位置,也就是末尾,同时oldS++newE--

第二步:

oldS = b, oldE = c 
newS = b, newE = e

比较结果:oldS 和 newS相等,需要把节点b移动到newS所对应的位置,同时oldS++,newS++

第三步:

oldS = c, oldE = c 
newS = c, newE = e

比较结果:oldS、oldE 和 newS相等,需要把节点c移动到newS所对应的位置,同时oldS++,oldE--,newS++

第四步:

oldS > oldE,则oldCh先遍历完成了,而newCh还没遍历完,说明newCh比oldCh多,所以需要将多出来的节点,插入到真实DOM上对应的位置上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值