vue3 设计目标
- 更小 (体积更小)
- 更快(主要体现在编译方面)
- 更友好(基于TS开发的,同时推出了组合式API ,大大增加了代码的逻辑组织能力 )
- 优化方案
性能提升主要通过哪些方面?
- 编译阶段
- diff算法优化:增加在静态标记,跳过静态标记的节点
- 自动静态提升:静态节点提升并复用
- 事件监听缓存:避免创建重复函数
- ssr优化
- 源码体积更小
- 响应式系统:
-
是使用proxy监听整个对象;但不兼容IE
-
1. 编译阶段优化-更快
diff时增加静态标记: 编译的时候会标记是否是动态变化的属性,静态标记的节点不需要更新;提高比较性能;
静态提升:vue3在编译过程中, 会对模板进行分析, 把那些不会随数据变化而改变的静态节点提取出来并进行提升,在后续的渲染中可以直接复用,避免了重复的创建和渲染,减少不必要的dom操作,提高了渲染效率,优化内存占用
事件监听缓存: 操作函数所在组件频繁更新的话, 每次更新都会创建函数实例,即使函数内部逻辑没有改变, 这可能造成一定的性能损耗 ,所以vue3为了避免这种不必要的函数重复创建的问题;提供了需要开发者借助useCallback 手动包裹 达到缓存的目的;
SSR优化: 当静态内容达到一定量级的时候,会用createStaticVnode方法在客户端去生成一个static node,这些静态node,会被直接innerHTML,就不需要创建对象,然后根据对象渲染
2. 体积优化- 更小
- 移除不常用的API:
beforeCreate 和 created生命周期;在setup函数里初始化$once单次监听属性被移除;推荐使用外部事件库或者新的通信机制来处理相关的需求- 过滤器filters; 用计算属性或者方法替代
$children
- 引入tree-shaking。去除死代码,使打包体积更小
2.1 Tree Shaking(清除多余代码优化打包体积的技术)
原理: 基于ES6模块语法,主要是借助ES6模块的静态编译思想,在编译的时候就确定了模块的依赖关系,以及输入和输出的变量;
vue实例是单例; vue3将全局API进行分块,如果你不使用某些功能,他们将不会包含在您的基础包里;
总结: 编译阶段确定哪些模块加载了,没使用的或者引用的删除
3. 数据劫持优化-更准确:
vue2的问题:
vue2 采用 Object.definePrototype 来劫持整个对象,然后深度遍历所有属性, 给所有属性加上getter 和setter,实现响应式;
但他不能监听到对象的新增,虽然vue2使用了set的方式解决了这个问题; 同时 嵌套层级比较深的情况下,就存在性能问题
vue3的解决方案:
vue3 采用proxy重写响应式系统,因为proxy可以对整个对象进行监听, 不需要深度遍历
- 可以监听动态属性的添加
- 可以监听到数组索引和数组length的属性
- 可以监听到删除属性
同时Proxy并不能监听到内部深层次的对象变化,而 Vue3的处理方式是
在getter 中去递归响应式,这样的好处是真正访问到的内部对象才会变成响应式,而不是无脑递归
4. 更友好-引入组合式api
为什么要引入组合式API? 组合式API 为什么更友好?
因为vue2 有以下问题:
- 代码的可读性随着组件的变大而变差
- 每一种代码复用的方式都存在缺点
- 比如多个mixins会造成命名冲突,数据来源不清晰
- typescript支持有限
组合式API的好处:
- 逻辑组织 和逻辑复用方面更优
- 函数式会有更好的类型推断
- 对 tree-shaking 友好,代码也更容易压缩
- 减少了this指向不明的情况:组合式中通常不使用this;
如果是小型组件,可以继续使用options API;