虚拟DOM
所谓虚拟DOM,就是用一个JS
对象来描述一个DOM
节点,像如下示例:
<div class="a" id="b">我是内容</div>
{
tag:'div', // 元素标签
attrs:{ // 属性
class:'a',
id:'b'
},
text:'我是内容', // 文本内容
children:[] // 子元素
}
我们把组成一个节点的必要东西通过一个JS
对象表示出来,那么这个JS
对象就可以用来描述这个DOM
节点,我们把这个JS
对象就称为是这个真实DOM
节点的虚拟DOM
节点。
虚拟DOM类型
注释节点、文本节点、元素节点、组件节点、函数是组件节点、克隆节点
其实虚拟DOM就是以js的计算性能来换取操作真实的DOM所消耗的性能。
DOM-Diff
在vue中,diff的过程就是一个patch的过程,也就是修改的过程,那么它要干的事就是 以新的newVNode为基准,改造旧的oldVNode,让它变成和新的newVNode一样,这就是patch的过程。整个过程分三部分:
创建节点:新的newVNode有的但是旧的oldVNod没有就要创建
删除节点:新的newVNode没有的但是旧的oldVNod有就要删除
更新节点:新、旧VNode里都有,就会以新的newVNode为准,更新旧的oldVNode
我们经常说的虚拟VNode是 oldVNode, 我们要更新的Vnode
更新节点
创建节点和删除节点都比较好理解,更新节点会复杂一些
在更新节点中也分为: 静态节点、文本节点、元素节点
静态节点:页面只需要加载一次的节点,不管数据怎么变化都不会改变的节点
<div>我是静态节点</div>
文本节点:节点中住包含文本
<div>{{message}}</div>
<div>这是{{text}}</div>
元素节点:包含子节点的元素,然后递归更新子节点
更新子节点(这里是更新子节点)
更新子节点分为:创建子节点、删除子节点、移动子节点、更新子节点
创建子节点
对比新旧VNode,把新创建的节点插入到所有未处理节点之前,后面不管有多少个新增的节点,每一个都插入到所有未处理节点之前,位置才不会错。
删除子节点
对比新旧VNode,newVNode里没有但oldVNode里有的节点就是要删除的节点。
更新子节点
和更新节点逻辑一样。
移动子节点
当新的子节点和旧的子节点找到了相同的子节点,但是位置不一样的时候,只需要调整位置就可以了。
外层循环newChildren数组,内层循环oldChildren数组。根据不同的情况做出不同的操作
优化更新子节点
如果按照上面说的更新子节点确实可以更新,但是如果数据量很大的话,计算的时间复杂度就会很高,不利于性能提升,vue同时做了优化提示的方法。
- newChildren数组里的所有未处理子节点的第一个子节点称为:新前旧前;
newChildren
数组里的所有未处理子节点的最后一个子节点称为:新后旧后;oldChildren
数组里的所有未处理子节点的第一个子节点称为:新后旧前;oldChildren
数组里的所有未处理子节点的最后一个子节点称为:新前旧后
如果理解这个,你就会明白,vue比那里不是简单的从前往后或者从后往前循环,而是从两边向中间循环。如果这4种情况都不对,那就常规循环遍历。