虚拟 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 属性支持函数