导航
目的:为了解决频繁操作 DOM 导致性能开销大的问题
方案:JS 运算效率 远高于 操作 DOM 效率,所以把真实 DOM 树抽象成 JS 对象树,运用 patch 算法 来用JS计算出真正需要更新的节点,最大限度地减少 DOM 操作,从而显著提高性能
Virtual DOM 其实就是一棵以 JavaScript 对象(vNode节点)作为基础的树,用对象属性来描述节点,实际
是一层对真实 DOM 的抽象。
基本成员:
例如:
<div id="app" class="container">
<h1>虚拟DOM</h1>
<ul style="color: orange">
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
</ul>
</div>
虚拟DOM表示:
{
tag: 'div',
props: {
id: 'app',
class: 'container'
},
children: [
{
tag: 'h1',
children: '虚拟DOM'
},
{
tag: 'ul',
props: { // 节点属性及绑定事件...
style: 'color: orange'
},
children: [
{
tag: 'li',
children: '第一项'
},
{
tag: 'li',
children: '第二项'
},
{
tag: 'li',
children: '第二项'
}
]
}
]
}
获取 template →
template 转 AST 语法树 →
AST 语法数 转 render 函数 →
render 函数 返回 VNode(虚拟DOM节点)

转化过程:
模板→ AST树→渲染函数→ 虚拟DOM→ 真实DOM
其中:
源代码的抽象语法的树状描述
把代码形成树状结构,然后对这个结构做分析、优化、处理,最终再把它转化为真正所需内容
说白了就是字符串解析、拼接、再解析、再拼接...
对源代码的数据结构化
模板中有 v-show 、v-if 、v-model 这些指令等其他内容,而这些内容是不能存在于虚拟 DOM 中的,因为真实 html 不需要它们,它们是框架所需的,类似这种东西全部都得转为 AST 后做处理,把这些多余的(相对真实html)属性都解析成对应功能并最终删除它们。例如
</div> => 帮用户补上 or 给警告<div id="app" style="color: red;font-size: 20px;">
hello
<h1>{{ name }}</h1>
<ul>
<li style="color: green">{{ age }}</li>
<li>{{ info.job }}</li>
</ul>
</div>
转为 👇🏻
{
tag: "div",
type: 1, // 1代表标签
attrs: [
{
name: 'id',
value 'app'
},
{
name: 'style',
value: {
'color': 'red',
'font-size': '20px'
}
}
],
children: [
{
type: 3, // 3代表文本
text: 'hello'
},
{
type: 1,
tag: 'h1',
attr: null,
children: [
{
type: 3,
text: '{{name}}'
}
]
}
]
}
这不是虚拟 DOM ,只是类似。虚拟 DOM 是描述 DOM 对象(节点)的,最终是要变成真实 DOM 的
虚拟 DOM 的最终目的就是将虚拟节点渲染到视图上。
上面的过程就是所谓的虚拟 DOM 的算法,也就是 diff 算法,它主要包括两个步骤:
新旧虚拟DOM对比的时候,Diff算法比较只会在同层级进行, 不会跨层级比较。所以Diff算法是:广度优先算法。 时间复杂度:O(n)

