简介

说明

        本文介绍Vue的虚拟DOM。

Vue的版本

        Vue 2.x 中模板渲染采用的是Virtual DOM。(Vue 1.x 采用的是 DocumentFragment)。

        Vue 2.x比Vue 1.0的渲染速度提升了2-4倍,并大大降低了内存消耗。

什么是虚拟DOM

        虚拟DOM(Virtual Dom)即虚拟节点。

        虚拟DOM在Vue.js里做了两件事:


  1. 创建JS对象(虚拟节点),用来模拟真实DOM节点。
  1. 该对象包含了真实DOM的结构及其属性
  1. 将虚拟节点与旧虚拟节点进行对比,然后更新视图(渲染)

比如dom是这样的:

<div id="wrap">
<p class="title">Hello world!</p>
</div>

虚拟DOM(伪代码)如下所示:

var VNode = {
tag:'div',
attrs:{
id:'wrap'
},
children:[
{
tag:'p',
text:'Hello world!',
attrs:{
class:'title',
}
}
]
};

模板转换成视图的过程


  1. Vue.js通过编译(compile)将template 模板转换成渲染函数
  2. 执行渲染函数(render) ,得到一个虚拟节点树
  3. 在对 Model 进行操作的时候,会触发对应 Dep 中的 Watcher 对象。

  1. Watcher 对象会调用对应的 update 来修改视图。
  2. 这个过程主要是将新旧虚拟节点进行差异对比,然后根据对比结果进行DOM操作来更新视图。


流程如下所示

Vue--虚拟DOM(virtual DOM)--详解_javascript

示例

Vue--虚拟DOM(virtual DOM)--详解_javascript_02

虚拟DOM的作用

操作真实 DOM 的代价

       原生 JS 或 JQuery 操作 DOM 时,浏览器会从构建 DOM 树开始从头到尾执行一遍渲染流程。

        比如:在一次操作中,我要更新 10 个 DOM 节点,浏览器收到第一个 DOM 请求后并不知道还有 9 次更新操作,因此会马上执行流程,最终执行10 次。第一次计算完时,紧接着下一个 DOM 更新请求,这个节点的坐标值就变了,前一次计算为无用功。

        计算 DOM 节点坐标值等都是白白浪费的性能。即使计算机硬件一直在迭代更新,操作 DOM 的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户体验。

        真实的DOM节点,哪怕一个最简单的div也包含着很多属性。

虚拟 DOM 的好处

        虚拟DOM就是为了解决直接操作DOM导致的性能问题而被设计出来的。

        使用了虚拟DOM之后,假如一次操作中有10次更新DOM的动作,虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attach到DOM树上,通知浏览器去执行绘制工作,这样可以避免大量的无用的计算量。

        Virtual DOM 本质上就是在 JS 和 DOM 之间做了一个缓存。可以类比 CPU 和硬盘,既然硬盘这么慢,我们就在它们之间加个内存。既然 DOM 这么慢,我们就在它们 JS 和 DOM 之间加个虚拟DOM。CPU(JS)只操作内存(Virtual DOM),最后的时候再把变更写入硬盘(DOM)。

        Virtual DOM的优势不在于单次的操作,而是在大量、频繁的数据更新下,能够对视图进行合理、高效的更新。

作用总结


  1. 提升渲染性能

  1. 操作 DOM 会导致渲染很慢(每次操作DOM都会触发回流和重绘)。
  2. 操作虚拟DOM实际是操作JS对象,可以将多次操作整合后再统一操作DOM。操作虚拟DOM时不会引起回流和重绘(即:不会引起渲染)

  1. 具备跨平台的优势
  1. Virtual DOM 基于JavaScript 对象而不依赖真实平台环境,所以它有跨平台的能力,比如:浏览器平台、Weex、Node 等。
  1. 提高开发速度
  1. 无需手动操作DOM:只需要写好View-Model的代码逻辑,框架会根据虚拟DOM和数据双向绑定,帮我们更新视图;

虚拟DOM的缺点

首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。