# 目录结构
vue3 使用了 lerna (opens new window) 这个多包管理器来管理项目里面的各个包,使用 lerna 的好处就是每个包可以单独发布,而不需要所有包一块发布。
现在很多著名的库都会使用 lerna 来管理项目里的包,比如:react、vue3 等等。使用 lerna 来管理的项目里都会有一个
packages
文件夹,整个项目的核心文件都在这个文件夹下。
# 整体架构
# Proxy
vue2 中使用 Object.defineProperty
来劫持对象属性,而 vue3 使用 proxy + reflect
来代理整个对象。使用 proxy 的优缺点如下:
优点
能够代理整个对象,并且能够处理多层属性的响应。之前的 Object.defineProperty 只能做到第一层属性的响应。
能够监听到数组或者对象新增/删除的 key。
支持 13 种拦截操作,功能更强大。
返回新对象而不是直接修改原对象,更符合 immutable。
缺点
- 兼容性差,目前没有一个完整支持 proxy 所有拦截方法的 polyfill 方案。
function reactive(data) {
if (typeof data !== "object" || data === null) {
return data;
}
const observed = new Proxy(data, {
get(target, key, receiver) {
// Reflect 有返回值不报错
let result = Reflect.get(target, key, receiver);
// 多层代理
return typeof result !== "object" ? result : reactive(result);
},
set(target, key, value, receiver) {
effective();
// proxy + reflect
const ret = Reflect.set(target, key, value, receiver);
return ret;
},
deleteProperty(target, key) {
const ret = Reflect.deleteProperty(target, key);
return ret;
}
});
return observed;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 模板编译
vue3 相对于 vue2 有一个很大的优化点就是模板编译解析不再是使用正则表达式去匹配了,而是自己定义了一套语法规则,通过分析 ast 抽象语法树,转化成 render 函数的方式去编译解析模板。
各种语言的语法规则可以查看 antlr/grammars-v4 (opens new window)。
# 所做的优化
1. 重写 vdom 机制
通过编译时的标记优化运行时的速度。
2. 优化插槽(slot)生成
原来的实现是,父组件重新渲染时子组件也必须同时渲染,而在 vue3 中子组件提取函数,可以分别渲染。
3. 静态树提升
没有响应式绑定的部分被提取出来作为常量,用到的时候不用再次执行它的渲染函数。
4. 静态属性提升
没有响应式绑定的组件属性(props)被提取出来作为常量,用到的时候不用再进行创建。
5. 项目结构优化
内部解耦,更好维护,支持了细粒度的 tree-shaking,比如可选的生命周期。