VUE 3.0 学习之优化的点

230 阅读3分钟

发展历程

1.0 到 2.0,最大的优化就是引入虚拟DOM的概念

2.0 的痛点:

  • 源码自身的维护性:数据量大后带来的渲染和更新的性能问题
  • 兼容性:想舍弃但为了兼容一直保留的鸡肋API

一共三点:源码、性能、自身API

源码优化

  • 目的是让代码更易于开发和维护
  • 使用monorepots 管理和开发源码,提升自身代码可维护性
  • 相对于 2.0 的源码组织方式,monorepo把这些模块拆分到不同的package中,每个package有各自的API、类型定义和测试

monorepo

  • 模块拆分更细化,职责划分更明确,模块之间的依赖关系更加明确,开发人员也更容易阅读、理解和更改所有模块源码,提高代码的可维护性
  • package(比如reactivity响应式库)是可以独立于Vue.js使用,如果用户只想使用Vue.js 3.0 的响应式能力,可单独依赖这个响应式库而不是去依赖整个Vue.js ,减小了引用的体积大小。

有类型的JavaScript:TypeScript

2.0 使用flow进行类型校验,但是flow对一些复杂场景类型的检查,支持的并不好,比如:

const propOptions: any = vm.$options.props // wtf flow?

3.0 使用ts的原因:
  • 首先ts 能支持复杂的类型推导
  • 由于源码使用ts编写,省去了单独维护d.ts 文件的麻烦
  • ts保持着一定频率的迭代和更新

性能优化

3.0在源码体积减少方面做的工作:
  1. 移除一些冷门的feature
  2. 引入tree-shaking的技术

tree-shaking:依赖ES2015模块语法的静态结构(即importexport),通过编译阶段的

静态分析,找到没有引入的模块并打上标记。

如果项目中没有引入TransitionkeepAlive等组件,那么他们对应的代码就不会打包。这样

也就间接的达到了减少包体积的目的。

数据劫持优化

实现DOM功能,就必须劫持数据的访问与更新
  • 通过数据的访问,建立数据和DOM的依赖关系
  • 实现DOM自动更新,就必须劫持数据的更新,也就是说当数据发生改变后能自动执行一段代码去更新DOM

1.0 和 2.0都是通过Object.defineProperty 劫持数据的getter setter

3.0 使用了Proxy API做数据劫持,由于劫持的是整个对象,所以对对象的属性的增加和删除都能监听到。缺点是:不能监听到内部深层次的对象变化,3.0的处理方式是在getter中递归响应式,好处是真正访问到内部对象才会变成响应式,而不是无脑递归,同时也提升了性能。

编译优化

new Vue --- init --- $mount --- compile --- render ---vnode --- patch --- DOM

响应式优化,除了在数据劫持时优化,还可以在patch阶段,通过在编辑阶段优化编译的结果,实现运行时patch过程的优化。

3.0 通过编译阶段对静态模板的分析,编译生成了Block tree

Block tree

  • Block tree是一个将模板基于动态节点指令切割的嵌套区块,每个区块内部的节点结构是固定的,每个区块只需要以一个Array来追踪自身包含的动态节点
  • 借助Block treeVue.js vnode更新性能由与模板整体大小相关提升为与动态内容的数量相关
3.0在编译阶段还包含对slot的编译优化、事件侦听函数的缓存优化,并且在运行时重写了diff算法

语法 API 优化:Composition API

优化逻辑组织

1.0 和 2.0 时,编写组件本质就是在编写一个 “包含了描述组件选项的对象”,称为 Options API,写法符合正常逻辑思维,易于理解。

Options API

  • Options API 的设计是按照methods、computed、data、props这些不同的选项分类
  • 当组件小的时候,这种分类一目了然;但是在大型组件中,一个组件可能有多个逻辑关注点
  • 当使用Options API 的时候,每一个关注点都有自己的Options
  • 如果需要修改一个逻辑关注点,就需要在单个文件中不断上下切换和寻找
Composition API
  • 将某个逻辑关注点相关的代码全都放在一个函数里
  • 这样当需要修改一个功能时,就不再需要在文件中跳来跳去

优化逻辑复用

2.0的 mixin 存在的问题:
  • 首先每个mixin都可以定义自己的props、data。它们之间是无感的,所以很容易定义相同的变量,导致命名冲突。
  • 对组件而言,如果模板中使用不在当前组件中定义的变量,那么就不太容易知道这些变量定义在哪里,导致数据来源不清晰。
3.0 的 Composition API解决了mixins的这两个问题。

Composition API的优点

  • 除了在逻辑复用方面的优势,也会有更好的类型支持
  • 因为他们都是一些函数,在调用函数时,自然所有的类型就被推导出来了,不像Options API 所有的东西使用this
  • Composition APItree-shaking 友好,代码更容易压缩