虚拟DOM
什么是虚拟DOM
简单来说虚拟DOM就是用JS来模拟DOM结构。相对于浏览器渲染出来的真是DOM。
//1.内存中生成一颗虚拟dom树 <div id="content"><p>2</p><ul class="list-group"></ul></div>
var vDom = {
tag:"div",
attr:{
id:"content"
},
children:[
{tag:"p",content:2},
{tag:"ul",attrs:{className:"list-group"}}
]
}
上面就是一个简单的虚拟DOM,可以将内存里的虚拟DOM渲染成真实DOM
虚拟DOM的作用
当用传统的api或jQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。比如当你在一次操作时,需要更新10个DOM节点,理想状态是一次性构建完成DOM树,再执行后续操作。但是浏览器没有那么智能,在收到第一个更新DOM请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程,显然前面几次都是白白浪费性能。而且操作DOM的代价是很昂贵的,频繁操作可能会出现页面卡顿,影响用户的体验。
虚拟DOM就是为了解决这个浏览器性能问题而被设计出来的,如果一次操作中有10次更新DOM的操作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存在本地的一个js对象中,最终将这个js对象一次性attach到DOM树上,通知浏览器去执行绘制工作,这样可以避免大量的无谓的计算量。
两个假设
当DOM改变的时候,他会使用Diff算法将改变以后的js对象树与原先的js对象树进行比较,这个比较是逐层比较的,当发现节点删除就删除,增加就增加,
但是由于他是一级一级进行比较的,这样就会有一个致命的缺点:假设在根元素上又嵌套了一个元素,那么Diff算法在比较第一层的时候就认为改变了,就相当于重新创建了一个JS对象树,这样效率还是不高,
此外,还有一个致命的缺点就是;如果同一级上有特别多个相同的元素,在增加或者排序的时候,就会在循环比较的时候浪费掉大量的性能
于是,为了解决这两个缺点,虚拟DOM做了两个假设,并且这两个假设也实现了,所以已经解决了这两个缺点
两个假设:
1、两个相同的组件产生类似的DOM结构,不同的DOM节点产生不同的DOM节点
2、对于同一个层次的一组节点,他们可以通过唯一的id进行区分
对于第二种假设,就是解释了我们为什么要在vue的v-for里面必须加一个key 并且这个key要是唯一的