Skip to content
On this page

虚拟 DOM

vdom 是实现 Vue 和 React 的重要基石;diff 算法是 vdom 中最核心、关键的部分。 DOM 操作非常耗费性能 ,有了一定的复杂度,想减少计算次数比较难,能不能把计算更多的转移到 JS 计算,因为 JS 执行速度很快,因此 vdom 出来了(用 JS 模拟 DOM 结构,计算出最小的变更,操作 DOM)。 如何模拟的?下面分别是 HTML 代码和 JS 代码:

html
<div id="div1" class="container">
	<p>vdom</p>
	<ul style="font-size: 20px">
		<li>a</li>
	</ul>
</div>
js
{
	tag: 'div',
	props: {
		className: 'container',
		id: 'div1',
	},
	children: [
		{
			tag: 'p',
			children: 'vdom'
		},
		{
			tag: 'ul',
			props: {
				style: 'font-size: 20px',
			},
			children: [
				{
					tag: 'li',
					children: 'a'
				},
			]
		}
	]
}

可以通过 snabbdom 来学习。snabbdom 是 vdom 库,易学易用,Vue2 也是参考它实现的 vdom 和 diff 。Vue3 重写 vdom 代码,优化其性能,总体 vdom 的基本理念不变。

vdom diff 算法

diff 是 vdom 的既核心又关键的部分。 树的 diff 算法的时间复杂度是 O(n^3)(遍历第一课树和第二棵树,然后还要排序),如果有 1000 个节点,要计算 1 亿次,这个算法一定不可用。 好在最后把时间复杂度优化到 O(n) 。怎么做的?

  • 只比较同一层级,不跨级比较;
  • tag 不相同,则直接删掉重建,不再深度比较;
  • tag 和 key ,两者都相同,则认为是相同节点,不再深度比较。 深入一下 snabbdom diff 算法,其中有个 patch 函数。

文章引荐: Vue2.0 和 Vue3.0 Dom Diff 对比 - 知乎 (zhihu.com)

Vue3 为什么使用 Proxy

  • 弥补 Object.defineProperty 的两个不足 a. 动态创建的 data 属性需要用 Vue.set 来赋值,删除属性需要用 Vue.delete 来操作,Vue 3 用了 Proxy 就不需要了; b. 基于性能考虑,Vue 2 篡改了数组的 7 个 API ,Vue 3 用了 Proxy 就不需要了;
  • defineProperty 需要提前递归地遍历 data 做到响应式,而 Proxy 可以在真正用到深层数据的时候再做响应式(惰性)

Vue 3 为什么使用 Composition API

尤雨溪的博客解说: https://zhuanlan.zhihu.com/p/68477600

  • Composition API 比 mixins、高阶组件、extends、Renderless Components 等更好,原因有三: a. 模板中的数据来源不清晰; b. 命名空间冲突; c. 性能
  • 更适合 TypeScript 。

Vue 3 对比 Vue 2 做了哪些改动

  • createApp() 代替了 new Vue()
  • v-model 代替了以前的 v-model 和 .sync
  • 根元素可以有多个元素
  • 新增 Teleport 传送门
  • destroyed 被改名为 unmounted 了(before 当然也改了)
  • ref 属性支持函数

Released under the MIT License.