为了给用户带来更好的编程体验,对Typescript更好的支持,对逻辑进行更多的复用,所以Vue.js3.0横空出世.
1-1:源码的优化
源码的优化主要体现在使用monorepo来进行管理各个模块和使用Typescript来进行开发源码
更好的代码管理方式:monorepo
相对于Vue.js 2.x的源码组织方式,monorepo 把这些模块拆分到不同的package中,每个package都有各自的API,类型定义和测试.
这样使得模块拆分更细化,职责划分更明确,模块之前的依赖关系也更加明确,开发人员也更容易阅读,理解,和更改所有模块源码,提高代码的可维护性.
举个例子:
package(比如reactivity响应式库)是可以独立于Vue.js使用的
这样用户如果只想使用Vue.js 3.0的响应式能力,可单独依赖这个响应式库而不用去依赖整个Vue.js 减少了引用包体积的大小,而Vue.js2.x是做不到这一点的
1-2:性能优化
在Vue.js3.0中为了减少源码体积,移除一些冷门的feature,引入tree-shaking的技术
移除一些冷门的feature很好理解 接下来就说一下tree-shaking
依赖ES2015模块语法的静态结构(即import和export) 通过编译阶段的静态分析,找到没有引入的模块并打上标记.
举个例子 我同时暴露了两个函数a函数和b函数 但是我并没有使用b函数那么打包时就会对b函数打上标记,在压缩阶段会利用压缩工具去删除这些没有利用到的代码.
如果你在项目中没有引入Transition,KeepAlive等组件,那么它们对应的代码就不会被打包,这样也就间接达到了减少项目引入的Vue.js包体积的目的
1-3:数据劫持优化
从Vue.js 1.0版本到现在数据响应式一直是伴随到现在,这也是很多人喜欢使用Vue.js的原因,数据更新改变视图,视图更新改变DOM,,实现这个功能必须劫持数据的访问和更新.
因为在渲染DOM的时候访问了数据,我们可以对它进行访问劫持,这样就在内部建立了依赖关系,也就知道数据对应的是哪一片DOM,从而实现数据更新改变DOM,DOM更新改变视图
在Vue2.x版本中使用Object.defineProperty这个API劫持数据的getter和setter,但是他需要知道要劫持的key,所以他就没有办法做到新增和删除功能,这也是为什么需要delete方法
比如我们在data中定义了一个嵌套层级比较深的对象,我需要使用里面定义的内容,那么Object.defineProperty需要遍历每一层对象都变成响应式对象那么毫无疑问,这对性能来说是非常浪费的
而在Vue.js 3.0版本中使用Proxy API来进行数据劫持,注意的是,ProxyAPI 并不能监听到内部深层次的对象变化,因此Vue.js3.0的处理方式是在getter中去递归响应式
1-4:编译优化
通过编译阶段对静态模板的分析,编译生成了block tree Block tree 是一个将模板基于动态节点指令切割的嵌套区块,将每个区块内部的节点结构是固定的 每个区块只需要以一个Array来追踪自身包含的动态节点
借助Block tree,Vue.js将Vnode更新性能与模板整体大小相关提升为与动态内容的数量相关
在编译阶段还包含了对Slot的编译优化,事件侦听函数的缓存优化,并且在运行时重写了diff算法
编写组件本质就是在编写一个"包含了描述组件选项的对象" 我们把他称作为Options API 这也是Vue.js 1.x 和Vue.js 2.x中所采用的,但是在Vue.js3.x版本中采用了Composition API
Options API的设计是按照methods,computed,data,props这些不同的选项分类 当组件小的时候,这种分类方式一目了然.但是在大型组件中,一个组件可能有多个逻辑关注点,但是用Options API的时候,每一个关注点都有自己的Options 如果需要修改一个逻辑关注点,就需要在单个文件中不断上下切换寻找
Composition API 就是将某个逻辑关注点相关的代码全部放在一个函数里 这样当需要修改一个功能时,就不再需要在文件中跳来跳去
在Vue2中采用mixin来进行逻辑混入,在Vue3中则使用hook函数来代替mixin
除了在逻辑复用方面有优势,也会有更好的类型支持,因为他们都是一些函数,再调用函数时,自然所有类型就被推导出来了,不像Options API所有的东西都使用this
另外Composition API对tree-shaking友好,代码也更容易压缩.
我的分享就到这里了可能有的地方说的太过于模糊 也希望大家能多多提提建议,之后我也会一直分享我对Vue3.0源码的分析和一些个人看法 也希望这篇文章能对大家起到一些帮助! 谢谢