0.前言
虚拟DOM概念随着react的诞生而诞生,由facebook提出,其卓越的性能很快得到广大开发者的认可;继react之后vue2.0也在其核心引入了虚拟DOM的概念。
1.真实DOM和其解析流程?
浏览器渲染引擎工作流程都差不多,大致分为5步,创建DOM树——创建StyleRules——创建Render树——布局Layout——绘制Painting
第一步,用HTML分析器,分析HTML元素,构建一颗DOM树(标记化和树构建)。
第二步,用CSS分析器,分析CSS文件和元素上的inline样式,生成页面的样式表。
第三步,将DOM树和样式表,关联起来,构建一颗Render树(这一过程又称为Attachment)。每个DOM节点都有attach方法,接受样式信息,返回一个render对象(又名renderer)。这些render对象最终会被构建成一颗Render树。
第四步,有了Render树,浏览器开始布局,为每个Render树上的节点确定一个在显示屏上出现的精确坐标。
第五步,Render树和节点显示坐标都有了,就调用每个节点paint方法,把它们绘制出来。
原生JS或JQ操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程。
操作DOM的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户体验,复杂度高,兼容性也较差
2.什么是虚拟DOM?优点?
虚拟DOM是轻量级的javaScript对象,当状态发生改变的时候,只更新需要被替换的DOM,不需要全部重绘。
虚拟DOM就是为了解决浏览器性能问题而被设计出来的
若一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一次性attch到DOM树上,再进行后续操作,避免大量无谓的计算量。所以,用JS对象模拟DOM节点的好处是,页面的更新可以先全部反映在JS对象(虚拟DOM)上,操作内存中的JS对象的速度显然要更快,等更新完成后,再将最终的JS对象映射成真实的DOM,交由浏览器去绘制。得益于js的执行速度,将原本需要在真实dom进行的创建节点,删除节点,添加节点等一系列复杂的dom操作全部放到vdom中进行,这样就通过操作vdom来提高直接操作的dom的效率和性能。
优点:基于JS计算的,开销比较小,执行效率高
3.Vue中虚拟DOM如何工作?
Vue在2.0版本也引入了vdom
let element={
tagName:'ul',//节点标签名
props:{//dom的属性,用一个对象存储键值对
id:'list'
},
children:[//该节点的子节点
{tagName:'li',props:{class:'item'},children:['aa']},
{tagName:'li',props:{class:'item'},children:['bb']},
{tagName:'li',props:{class:'item'},children:['cc']}
]
}
对应的html写法是:
<ul id='list'>
<li class='item'>aa</li>
<li class='item'>aa</li>
<li class='item'>aa</li>
</ul>
Virtual DOM最主要的还是保留了Element之间的层次关系和一些基本属性. 你给我一个数据,我根据这个数据生成一个全新的Virtual DOM,然后跟我上一次生成的Virtual DOM去 diff,得到一个Patch,然后把这个Patch打到浏览器的DOM上去。
2.1VNode对象
一个VNode的实例对象包含了以下属性
-
tag: 当前节点的标签名 -
data: 当前节点的数据对象(VNodeData代码定义)
-
children: 数组类型,包含了当前节点的子节点 -
text: 当前节点的文本,一般文本节点或注释节点会有该属性 -
elm: 当前虚拟节点对应的真实的dom节点 -
ns: 节点的namespace -
context: 编译作用域 -
functionalContext: 函数化组件的作用域 -
key: 节点的key属性,用于作为节点的标识,有利于patch的优化 -
componentOptions: 创建组件实例时会用到的选项信息 -
child: 当前节点对应的组件实例 -
parent: 组件的占位节点 -
raw: raw html -
isStatic: 静态节点的标识 -
isRootInsert: 是否作为根节点插入,被<transition>包裹的节点,该属性的值为false -
isComment: 当前节点是否是注释节点 -
isCloned: 当前节点是否为克隆节点 -
isOnce: 当前节点是否有v-once指令
2.2VNode分类
-
EmptyVNode: 没有内容的注释节点 -
TextVNode: 文本节点 -
ElementVNode: 普通元素节点 -
ComponentVNode: 组件节点 -
CloneVNode: 克隆节点,可以是以上任意类型的节点,唯一的区别在于isCloned属性为true
下一篇 什么是render函数?
参考文献:
1.作者:LoveBugs_King
链接:https://www.jianshu.com/p/af0b398602bc
2.https://github.com/DDFE/DDFE-blog/issues/18
3.https://segmentfault.com/a/1190000013469565