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作比较。在别处看到的一张很形象的图:
4.diff算法结合着key值理解:
当我们想在a,b,c,d,e这四个节点的d之前c之后插入一个z节点。
当我们不使用key值的时候,由于没有key值不知道当前具体在更新谁,因此做的操作就是见到谁就更新谁。
具体过程:先更新a,b,c(这三个的更新操作一样),但因为没有key值,到d的时候不清楚是不是自己,但只能认为是自己,所以只好覆盖更新,再把后的e更新到d,更新完后再创建新的追加到后面。
在这个过程中进行了五次更新操作,一次追加操作。
上图是使用key值的情况,前三个一样不再说,到d和z比较时发现不一样,由于源码中首尾判断假猜策略,发现尾部的e和d对应相同,就从后开始更新,到最后只剩下z,再最后创建新的z追加到相应位置(c的后面)。
在这个过程中也进行了五次更新操作,一次追加操作。
那么照操作次数来看,难道就说明不管有没有key值,都是干着同一样的事吗?
但其实并不是这样,主要的不是更新操作次数,而是更新到底有没有发生,虽然在有key值下尝试去更新5次,但实际上并未进行任何操作,因为前面5次都在更新完全相同的5个结点,实际上只有最后的一次创建操作。但不使用key值,则如上图d-z,e-d发生新旧节点更新。