浅谈diff算法

1. 当数据发生变化时,vue是怎么更新节点的

要知道渲染真实DOM的开销是很大的,比如有时候我们修改了某个数据,如果直接渲染到真实dom上会引起整个dom树的重绘和重排,有没有可能我们只更新我们修改的那一小块dom而不要更新整个dom呢?

2. virtual DOM和真实DOM的区别

virtual DOM是将真实的DOM的数据抽取出来,以对象的形式模拟树形结构。比如dom是这样的:

<div>
    <p>123</p>
</div>

对应的virtual DOM(伪代码):

var Vnode = {
    tag: 'div',
    children: [
        { tag: 'p', text: '123' }
    ]
};

3. diff的比较方式

在采取diff算法比较新旧节点的时候,比较只会在同层级进行, 不会跨层级比较。

<div>
    <p>123</p>
</div>

<div>
    <span>456</span>
</div>

上面的代码会分别比较同一层的两个div以及第二层的p和span,但是不会拿div和span作比较。在别处看到的一张很形象的图:
1.png

4.diff算法结合着key值理解:

当我们想在a,b,c,d,e这四个节点的d之前c之后插入一个z节点。

2.png

当我们不使用key值的时候,由于没有key值不知道当前具体在更新谁,因此做的操作就是见到谁就更新谁。
具体过程:先更新a,b,c(这三个的更新操作一样),但因为没有key值,到d的时候不清楚是不是自己,但只能认为是自己,所以只好覆盖更新,再把后的e更新到d,更新完后再创建新的追加到后面。
在这个过程中进行了五次更新操作,一次追加操作。

3.png

上图是使用key值的情况,前三个一样不再说,到d和z比较时发现不一样,由于源码中首尾判断假猜策略,发现尾部的e和d对应相同,就从后开始更新,到最后只剩下z,再最后创建新的z追加到相应位置(c的后面)。
在这个过程中也进行了五次更新操作,一次追加操作。
那么照操作次数来看,难道就说明不管有没有key值,都是干着同一样的事吗?
但其实并不是这样,主要的不是更新操作次数,而是更新到底有没有发生,虽然在有key值下尝试去更新5次,但实际上并未进行任何操作,因为前面5次都在更新完全相同的5个结点,实际上只有最后的一次创建操作。但不使用key值,则如上图d-z,e-d发生新旧节点更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值