面试题:vue3 为什么更小更快更友好?

197 阅读4分钟

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的好处:

  1. 逻辑组织 和逻辑复用方面更优
  2. 函数式会有更好的类型推断
  3. 对 tree-shaking 友好,代码也更容易压缩
  4. 减少了this指向不明的情况:组合式中通常不使用this;

如果是小型组件,可以继续使用options API;