虚拟DOM
1. 什么是虚拟DOM?
虚拟DOM(Virtual Dom),也就是我们常说的虚拟节点,是用JS对象来模拟真实DOM中的节点,该对象包含了真实DOM的结构及其属性,用于对比虚拟DOM和真实DOM的差异,从而进行局部渲染来达到优化性能的目的。
举个栗子,真实的元素节点:
<div id="wrap">
<p class="title">Hello world!</p>
</div>
VNode:
{
tag:'div',
attrs:{
id:'wrap'
},
children:[
{
tag:'p',
text:'Hello world!',
attrs:{
class:'title',
}
}
]
}
2. 为什么使用虚拟DOM?
那在Vue和React框架中进行前端开发用到虚拟dom会有什么好处呢?
起初我们在使用JS/JQuery时,不可避免的会大量操作DOM,而DOM的变化又会引发回流或重绘,从而降低页面渲染性能。那么怎样来减少对DOM的操作呢?此时虚拟DOM应用而生,所以虚拟DOM出现的主要目的就是为了减少频繁操作DOM而引起回流重绘所引发的性能问题的。
3. 虚拟DOM的作用是什么?
1)兼容性好。因为Vnode本质是JS对象,所以不管Node还是浏览器环境,都可以操作;
2)减少了对Dom的操作。页面中的数据和状态变化,都通过Vnode对比,只需要在比对完之后更新DOM,不需要频繁操作,提高了页面性能;
4. 虚拟DOM和真实DOM的区别?
虚拟DOM和真实DOM的区别大概如下:
1)虚拟DOM不会进行回流和重绘;
2)真实DOM在频繁操作时引发的回流重绘导致性能很低;
3)虚拟DOM频繁修改,然后一次性对比差异并修改真实DOM,最后进行依次回流重绘,减少了真实DOM中多次回流重绘引起的性能损耗;
4)虚拟DOM有效降低大面积的重绘与排版,因为是和真实DOM对比,更新差异部分,所以只渲染局部;
DIFF算法
当数据变化时,vue如何来更新视图的?其实很简单,一开始会根据真实DOM生成虚拟DOM,当虚拟DOM某个节点的数据改变后会生成一个新的Vnode,然后VNode和oldVnode对比,把不同的地方修改在真实DOM上,最后再使得oldVnode的值为Vnode。
diff过程就是调用patch函数,比较新老节点,一边比较一边给真实DOM打补丁(patch);
- 如果是同一节点,执行patchVnode进行子节点比较;
- 如果不是同一节点,新节点直接替换老节点;
- 那如果不是同一节点,但是它们子节点一样怎么办?要牢记:diff是同层比较,不存在跨级比较的!简单提一嘴,React中也是如此,它们只是针对同一层的节点进行比较。
通过对比:
1.React渲染机制:React采用虚拟DOM,在每次属性和状态发生变化时,render函数会返回不同的元素树,然后对比返回的元素树和上次渲染树的差异并对差异部分进行更新,最后渲染为真实DOM。
2.diff永远都是同层比较,如果节点类型不同,直接用新的替换旧的。如果节点类型相同,就比较他们的子节点,依次类推。通常元素上绑定的key值就是用来比较节点的,所以一定要保证其唯一性,一般不采用数组下标来作为key值,因为当数组元素发生变化时index会有所改动。
3.渲染机制的整个过程包含了更新操作,将虚拟DOM转换为真实DOM,所以整个渲染过程就是Reconciliation。而这个过程的核心又主要是diff算法,利用的是生命周期shouldComponentUpdate函数。