发展历程
vue.js1.x-----vue.js2.x 引入了虚拟DOM
vue.js2.x问题
1)源码自身的维护性
数据量大后带来的渲染和更新的性能问题
2)兼容性
想舍弃但为了兼容一直保留的鸡肋API
vue3.0的优化
1)首先是源码优化,vue.js框架本身的优化
目的是让代码更易于开发和维护
源码的优化主要体现在使用monorepo和typescript管理和开发源码,这样做的目标是提升自身代码的可维护性
vue.js3如上图所示
相对于vue.js2.x的源码组织方式,monorepo把这些模块拆分到不同的package中,每个package有各自的API,类型定义和测试,这样使得模块拆分更细化,职责划分更明确,模块之间的依赖关系也更加明确,开发人员也更容易阅读,理解和更改所有模块源码,提高代码的可维护性。
package(比如reactivity响应库)是可以独立于vue.js使用,这样用户如果只想要使用vue.js的响应式能力,可单独依赖这个响应式库而不用去依赖整个vue.js,减少了引用包的体积大小,而vue.js2.x是做不到这一点的
源码编写语言:vue.js1.x原生开发,vue.js2.x使用flow,vue.js3.x使用typescript
2)性能优化
源码体积的优化,移除一些冷门的feature,引入tree-shaking技术
数据劫持优化,当数据改变后,为了自动更新DOM,那么就必须劫持数据的更新,也就是说当数据发生改变后能自动执行一些代码去更新DOM
通过object.defineProperty这个API的劫持数据的getter和setter,必须知道拦截的key是什么,嵌套层级比较深的对象、
vue3.0使用proxy api劫持整个对象,注意⚠️proxy api并不能监听到内部深层次对象的变化,因此,vue3.0的处理方式是在getter中去递归响应式,这样的好处是真正访问内部对象才会变成响应式,而不是无脑递归,无疑在很大程度上提升了性能
3)编译优化
通过在编译阶段优化编译的结果,实现运行时patch过程的优化
通过编译阶段对静态模版的分析,编译生成了block tree
block tree是一个将模版基于动态节点指令切割的嵌套区块,每个区块内部的节点结构是固定的,每个区块只需要以一个Array来追踪自身包含的动态节点
借助block tree,vue.js将vnode更新性能由与模版整体大小相关提升为与动态内容的数量相关
4)优化逻辑组织
vue.js1.x vue.js2.x 编写组件本质就是在编写一个包含了描述组件选项的对象,我们称它为options API
options api按照methods,computed,data,props这些不同的选项分类,组件小的时候,这种方式一目了然,但大型组件,一个组件可能有多个逻辑关注点,当使用options api的时候,每个关注点都有自己的options
vue.js3.0提供了新的api:compsositon api,就是将某个逻辑的关注点相关的代码都全部放进一个函数里,这样当需要修改一个功能时,就不需要在文件夹中跳来跳去
5)优化逻辑复用
vue.js 2.x mixin
首先每个mixin都可以定义自己的props,data,他们之间无感,所以很容易定义相同的变量,导致命名冲突
对组件而言,如果模版中使用不在当前组件中定义的变量,那么就会不太容易知道这些变量在哪里定义的,这就是数据来源不清晰
compsositon api解决以上两个问题
除了逻辑复用,也会有更好的类型支持,因为他们都是一些函数,在调用函数时,自然所有类型都推导出来了,不像options api所有东西使用this,compsositon api对tree shaking友好,代码易于压缩