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如何工作?

Vue2.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代码定义)

      Render函数之一《什么是虚拟DOM》

  • 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分类

Render函数之一《什么是虚拟DOM》

  • 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

相关文章: