前言
vue3.0正式版本终于在九月低发布了,本人在实习的过程中主要进行的项目也是基于Vue3.0的Beta版本composition-api开发的,就抱着热情学习了下Vue3.0,并在此做如下总结。
Vue3.0优化
源码优化
源码的优化主要体现在使用 monorepo (更好的代码管理方式)和 TypeScript (有类型的JavaScript语言)管理和开发源码,这样做的目标是提升自身代码可维护性。
性能优化
性能优化主要体现在:源码的体积优化、数据劫持优化、编译优化
- 源码的体积优化
静态资源的体积减少,网络对包的传输时间也会相应的减少,JavaScript解析包的时间也会减少. Vue3.0主要通过移除一些冷门的feature以及tree-shakiing(通过编译阶段的静态分析,找到没有被引用的代码并做上标记)
举个例子:
src/math.js
export function cube(x) {
return x*x*x;
}
export function square(x) {
return x*x;
}
src/index.js
import { cube } from ./math.js
dist/bundle.js
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* unused harmony export square */
/* harmony export (immutable) */ __webpack_exports__["a"] = cube;
function square(x) {
return x * x;
}
function cube(x) {
return x * x * x;
}
build后我们发现没有被import的square被做上了标记,然后的压缩阶段会利用压缩工具删除这些没有被使用的代码.
- 数据劫持优化
Vue区分与React的一点是它的数据是响应式的,DOM是数据的一种映射,数据发生修改会自动的响应式的影响DOM,把我们的目光集中在数据而不是视图.这就需要通过数据的劫持,在数据发生更新的时候去自动的更新DOM.这就需要在渲染DOM的时候对其进行依赖收集(源码地址)通过watcher进行依赖的管理,参考下图:
Vue.js 1.x 和 Vue.js 2.x 内部都是通过 Object.defineProperty 这个 API 去劫持数据的 getter 和 setter,具体是这样的:
Object.defineProperty(data, 'a',{
get(){
// track
},
set(){
// trigger
}
})
这个API的缺陷是我们要知道需要劫持的数据的key,因此我们不能检测对象属性添加或者删除,vue通过set和delete实例方法解决了如下问题,但是他还存在这另一个问题,当我们嵌套的层级较深的时候,如果我们要劫持深层次的属性,就需要遍历这个对象,显然这有着很大的性能负担.
Vue.js 3.0 使用了 Proxy API 做数据劫持,它的内部是这样的:
observed = new Proxy(data, {
get() {
// track
},
set() {
// trigger
}
})
由于它劫持的是整个对象,那么自然对于对象的属性的增加和删除都能检测到,但要注意的是,Proxy API 并不能监听到内部深层次的对象变化,因此 Vue.js 3.0 的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部对象才会变成响应式,而不是无脑递归,这样无疑也在很大程度上提升了性能。
- 编译优化
这是vue从new Vue 开始到生成DOM的过程,Vue3.0主要进行的优化在patch阶段,举个例子:
假设我们的代码是这样的:
<template>
<div id="content">
<p class="text">static text</p>
<p class="text">static text</p>
<p class="text">{{message}}</p>
<p class="text">static text</p>
<p class="text">static text</p>
</div>
</template>
我们可以看到这里面只有一个动态节点,但在Vue2.x的版本进行diff的时候我们仍然遍历了所有节点,这就导致了vNode的性能和我们模版的大小正相关的关系,和我们动态节点的数量无关,当一些组件的整个模版内只有少量动态节点时,这些遍历都是性能的浪费。
Vue.js 3.0 做到了,它通过编译阶段对静态模板的分析,编译生成了 Block tree。借助 Block tree,Vue.js 将 vnode 更新性能由与模版整体大小相关提升为与动态内容的数量相关
语法 API 优化:Composition API
使用composition-api达到了:优化逻辑组织、优化逻辑复用
- 优化逻辑组织
在vue之前的版本中我们使用Options API去编写组件:主要包括data、computed、methods、props这些选项去分类,当组件很小的时候,可以说是十分的清晰的,但是当我们的组件的代码量十分庞大的时候,我们想要搞清楚一些逻辑就会产生一些“反复横跳”的操作,Vue.js 3.0 提供了一种新的 API:Composition API,它有一个很好的机制去解决这样的问题,就是将某个逻辑关注点相关的代码全都放在一个函数里,这样当需要修改一个功能时,就不再需要在文件中跳来跳去。
- 优化逻辑复用
在我们开发的比较复杂的时候,尤其是中后台系统,少不了一些复用的逻辑,在之前的vue版本中我们通常用minxins去复用逻辑:
定义一个混入对象
export const myMinxin = {
data() {
return {
name: 'qimukakax'
}
},
methods: {
getToken() {
const params = 'qimukakax'
getToken(params)
}
}
}
将对象混入当前的模版
<template>
<div>components</div>
</template>
<script>
import { myMinxin } from './minxin.js'
export defaut {
minxins: [myMinxin],
created() {
console.log(this.name)//qimukakax
}
}
</script>
使用单个 mixin 似乎问题不大,但是当我们一个组件混入大量不同的 mixins 的时候,会存在两个非常明显的问题:命名冲突和数据来源不清晰。在composition-api中:
定义一个混入对象
import {ref} from 'vue'
export const useMyMinxin = {
const name = ref('qimukakax')
const getToken = () => {
const params = 'qimukakax'
getToken()
}
}
将对象混入当前的模版
<template>
<div>components</div>
</template>
<script>
import useMyMinxin from './minxin.js'
import { onMounted } from 'vue'
export defaut {
setup() {
const { name, getToken } = useMyMinxin()
onMounted(() => console.log(name))
}
}
</script>
可以看到这样我们的条理变得清晰的一点,Composition API 除了在逻辑复用方面有优势,也会有更好的类型支持,因为它们都是一些函数,在调用函数时,自然所有的类型就被推导出来了,不像 Options API 所有的东西使用 this。另外,Composition API 对 tree-shaking 友好,代码也更容易压缩。
写在后面
(个人学习笔记,待完善)
参考资料
Vue.js 3.0 核心源码解析 黄轶
其中还引用了一些大佬的帖子,都留下链接?啦! 大家加油?!
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!