跳到主要内容

认识

2023年06月10日
柏拉文
越努力,越幸运

一、认识


虚拟 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 会完成一下两种操作:

  1. 一个运行时渲染器将会遍历整个虚拟 DOM,并据此构建真实的 DOM 树。这个过程被称为挂载 (mount)

  2. 如果我们有两份虚拟 DOM 树,渲染器将会有比较地遍历它们,找出它们之间的区别,并应用这其中的变化到真实的 DOM 上。这个过程被称为更新 (patch),又被称为比对(diffing)协调(reconciliation)

虚拟 DOM 带来的主要收益是它让开发者能够灵活、声明式地创建、检查和组合所需 UI 的结构,同时只需把具体的 DOM 操作留给渲染器去处理。

二、细节


h 函数根据 type 的不同, 分别创建不同类型的 VNode:

  • string: 创建 Element VNode

  • object: 创建 Component VNode

  • other: 直接创建以 type 为类型的节点, 比如 Text VNodeComment VNodeFragment 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 虚拟节点。