Why虚拟DOM?
Vue在2.0版本引入虚拟DOM,这被认为是革命性的成果,因为虚拟DOM大大地提高了页面的渲染速度。
What虚拟DOM?
虚拟DOM是一个JavaScript对象,它是页面中真实DOM元素在JavaScript执行内存中的映射,由虚拟DOM来与数据状态(即在Vue中使用的数据变量)来进行绑定,而非真实DOM元素。
HOW虚拟DOM?
模板编译将Vue实例的模板进行解析编译并生成渲染函数,通过这个渲染函数我们可以构建出虚拟DOM。
有关模板编译生成渲染函数的可以看我的另一篇文章 : Vue源码分析② 模板编译
现在我们开始分析源码,看渲染函数是如何生成虚拟DOM的,还有虚拟DOM(下面统一称为VNode)是如何提高Vue应用的渲染速度的。
生成VNode
上面我们提到,VNode实际上就是通过执行渲染函数生成的,那么我们来看一看渲染函数的执行过程:
渲染函数的格式一般为:
with(obj){
return _c('div',
[
_c('h1',
{
style:({fontSize: title.size})
},
[
_v(_s(title.text))
]),
_v(_s(content))
])
}
其中 _c 是最主要的方法,用于形成普通VNode,而_v则是生成一个文本VNode,_s则是解析出表达式的值。
_c主要就是调用VNode的构造函数,然后构造函数用我们渲染函数中的信息,如 tag(节点名)、attrs(节点属性)、children(子节点列表)等生成一个VNode实例。
我们可以看一下VNode的构造函数:
var VNode = function VNode (
tag,
data,
children,
text,
elm,
context,
componentOptions,
asyncFactory
) {
this.tag = tag;
this.data = data;
this.children = children;
this.text = text;
this.elm = elm;
this.ns = undefined;
this.context = context;
this.fnContext = undefined;
this.fnOptions = undefined;
this.fnScopeId = undefined;
this.key = data && data.key;
this.componentOptions = componentOptions;
this.componentInstance = undefined;
this.parent = undefined;
this.raw = false;
this.isStatic = false;
this.isRootInsert = true;
this.isComment = false;
this.isCloned = false;
this.isOnce = false;
this.asyncFactory = asyncFactory;
this.asyncMeta = undefined;
this.isAsyncPlaceholder = false;
};
其实就是将各项属性值给设置进去而已,没有任何的逻辑操作。
VNode的使用
当我们构建出VNode时,肯定要将它用来渲染到真实的页面上,下面我们来看一下执行过程:
首次渲染
当节点是首次渲染时,即在Vue应用启动后该节点是第一次使用,那么我们直接提供VNode创建出真实的DOM元素,并插入到页面中,这样我们便完成了VNode的渲染。
二次渲染
二次渲染指的是在我们渲染VNode时,之前已经渲染过VNode了,旧的VNode已经生成真实的DOM元素并存在于页面中了,那么我们应该对渲染出的新VNode和旧VNode进行对比(patch),找出两者的不同点,并根据不同点对页面中的某些DOM元素进行删除并插入新增的DOM元素,过程如下:
let component = new Vue({
el: '#app',
template: `
<div>
<h1>{{title}}</h1>
<ul>
<li v-for='(name,index) in list' :key= 'index'>
{{name}}
</li>
</ul>
</div>
`,
data(){
return{
title: 'the title of Vue component',
list: ['Jhon', 'Judy', 'Sandy']
}
}
})
component.title = 'the new title of Vue component'
component.list = ['Jhon', 'Jim', 'Judy']
我们将对上述过程进行流程图的分析:
看完上面的流程图,我们可能会疑惑,为什么在修改 ul 中的 li 节点,需要规定插入到哪个节点的前面,现在我们用思维导图来分析一下:
蓝色节点未已处理,橙色节点为未处理
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: runcode 原文链接:https://juejin.im/post/6949812233819914270