认识
一、认识
虚拟 DOM
(Virtual DOM
,简称 VDOM
) 是一种编程概念,意为将目标所需的 UI
通过数据结构虚拟地表示出来,保存在内存中,然后将真实的 DOM
与之保持同步。与其说虚拟 DOM
是一种具体的技术,不如说是一种模式,所以并没有一个标准的实现。以 Vue3
示例, vnode
是这样的:
// 真实 DOM
<div id='hello'><div>
// 虚拟 DOM
const vnode = {
type: 'div',
props: {
id: 'hello'
},
children: [
/* 更多 vnode */
]
}
vnode
是一个 JavaScript
的对象, 它包含我们创建实际元素所需的所有信息。同时包含更多的子节点。通过 vnode
会完成一下两种操作:
-
一个运行时渲染器将会遍历整个虚拟
DOM
树,并据此构建真实的DOM
树。这个过程被称为挂载 (mount
)。 -
如果我们有两份虚拟
DOM
树,渲染器将会有比较地遍历它们,找出它们之间的区别,并应用这其中的变化到真实的DOM
上。这个过程被称为更新 (patch
),又被称为比对(diffing
) 或协调(reconciliation
)。
虚拟 DOM
带来的主要收益是它让开发者能够灵活、声明式地创建、检查和组合所需 UI
的结构,同时只需把具体的 DOM
操作留给渲染器去处理。
二、细节
h
函数根据 type
的不同, 分别创建不同类型的 VNode
:
-
string
: 创建Element VNode
-
object
: 创建Component VNode
-
other
: 直接创建以type
为类型的节点, 比如Text VNode
、Comment VNode
、Fragment VNode
等。
2.1 元素 VNode
const vnode = h(
'div',
{
class: 'test',
key: 1
},
'hello render'
);
2.2 组件 VNode
render
组件 VNode
const component = {
render() {
return h('div', {}, '我是一个 Component');
}
};
const vnode = h(component);
template
组件 VNode
const component = {
template: `<div> 我是一个 Component </div>`
};
const vnode = h(component);
2.3 Text VNode
const vnode = h(Text, '这是一个 Text');
console.log('vnode', vnode);
2.4 Comment VNode
const vnode = h(Comment, '这是一个 Comment');
console.log('vnode', vnode);
2.5 Fragment VNode
const vnode = h(Fragment, '这是一个 Fragment');
console.log('vnode', vnode);
三、问题
3.1 Vue3.0 针对 Vue2.0 所做的 Diff 优化?
Vue3.0
针对 Vue2.0
所有的 Diff
优化:
-
Vue2.0
:Vue2.0 Diff
算法是双端对比算法。其中主要的机制是: 在新旧字节点的头尾节点,也就是四个节点之间进行对比,找到可复用的节点,不断向中间靠拢的过程 -
Vue3.0
:Vue3.0 Diff
算法是快速选择算法。其中主要的机制是: 同步头部节点, 同步尾部节点, 新增新的节点, 删除多余节点, 处理未知子序列(贪心 + 二分处理最长递增子序列)
3.2 Vue Template VS React JSX
React JSX
: React
是纯运行时前端框架, 没有机会进行编译优化。React
借助 Babel
与 @babel/plugin-transform-react-jsx
得到包含 jsx
函数的解析结果, jsx
函数用于生成 React.Element
。
Vue Template
: Vue Template
同时支持编译时 + 运行时, 在模版编译的时候可以进行非常好的性能优化, 比如: 动态标记、静态节点提升等。 Vue Template
是通过 Vue
自身实现的编译器解析, 最终生成 render
函数, render
函数内部通过 h
函数生成 VNode
虚拟节点。