一、什么是虚拟DOM
虚拟 DOM (Virtual DOM
)这个概念相信大家都不陌生,从 React
到 Vue
,虚拟 DOM
为这两个框架都带来了跨平台的能力(React-Native
和 Weex
)
实际上它只是一层对真实DOM
的抽象,以JavaScript
对象 (VNode
节点) 作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实环境上
在Javascript
对象中,虚拟DOM
表现为一个 Object
对象。并且最少包含标签名 (tag
)、属性 (attrs
) 和子元素对象 (children
) 三个属性,不同框架对这三个属性的名命可能会有差别
创建虚拟DOM
就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM
对象的节点与真实DOM
的属性一一照应
在vue
中同样使用到了虚拟DOM
技术
定义真实DOM
<div id="app">
<p class="p">节点内容</p>
<h3>{
{ foo }}</h3>
</div>
实例化vue
const app = new Vue({
el:"#app",
data:{
foo:"foo"
}
})
观察render
的render
,我们能得到虚拟DOM
(function anonymous(
) {
with(this){
return _c('div',{
attrs:{
"id":"app"}},[_c('p',{
staticClass:"p"},
[_v("节点内容")]),_v(" "),_c('h3',[_v(_s(foo))])])}})
通过VNode
,vue
可以对这颗抽象树进行创建节点,删除节点以及修改节点的操作, 经过diff
算法得出一些需要修改的最小单位,再更新视图,减少了dom
操作,提高了性能
二、为什么需要虚拟DOM
DOM
是很慢的,其元素非常庞大,页面的性能问题,大部分都是由DOM
操作引起的
真实的DOM
节点,哪怕一个最简单的div
也包含着很多属性,可以打印出来直观感受一下:
由此可见,操作DOM
的代价仍旧是昂贵的,频繁操作还是会出现页面卡顿,影响用户的体验
举个例子:
你用传统的原生api
或jQuery
去操作DOM
时,浏览器会从构建DOM
树开始从头到尾执行一遍流程
当你在一次操作时,需要更新10个DOM
节点,浏览器没这么智能,收到第一个更新DOM
请求后,并不知道后续还有9次更新操作,因此会马上执行流程,最终执行10次流程
而通过VNode
,同样更新10个DOM
节点,虚拟DOM
不会立即操作DOM
,而是将这10次更新的diff
内容保存到本地的一个js
对象中,最终将这个js
对象一次性attach
到DOM
树上,避免大量的无谓计算
很多人认为虚拟 DOM 最大的优势是 diff 算法,减少 JavaScript 操作真实 DOM 的带来的性能消耗。虽然这一个虚拟 DOM 带来的一个优势,但并不是全部。虚拟 DOM 最大的优势在于抽象了原本的渲染过程,实现了跨平台的能力,而不仅仅局限于浏览器的 DOM,可以是安卓和 IOS 的原生组件,可以是近期很火热的小程序,也可以是各种GUI
三、如何实现虚拟DOM
首先可以看看vue
中VNode
的结构
源码位置:src/core/vdom/vnode.js
export default class VNode {
tag: string | void;
data: VNodeData | void;
children: ?Array<VNode>;
text: string | void;
elm: Node | void;
ns: string | void;
context: Component | void; // rendered in this component's scope
functionalContext: Component | void; // only for functional component root nodes
key: string | number | void;
componentOptions: VNodeComponentOptions | void;
componentInstance: Component |
标签:DOM,void,VNode,虚拟,操作,思路,节点
From: https://blog.csdn.net/jiadsadfasfs/article/details/142849312