Vue3 和 Vue2 的区别
Vue3 框架的优点特点
- 首次渲染更快
diff
算法更快- 内存占用更少
- 打包体积更小
- 更好的
Typescript
支持 Composition API
组合
生命周期
对于生命周期来说,整体上变化不大,只是大部分生命周期钩子名称上 + on
,功能上是类似的。不过有一点需要注意,Vue3
在组合式 Composition API
中使用生命周期钩子时需要先引入,而 Vue2
在选项 Options API
中可以直接调用生命周期钩子,如下所示:
Vue2 | Vue3 | 说明 |
---|---|---|
beforeCreate | setup | 组件创建之前,执行初始化任务 |
created | setup | 组件创建完成,访问数据、获取接口数据 |
beforeMount | onBeforeMount | 组件挂载之前 |
mounted | onMounted | 组件挂载完成,DOM 已创建,访问数据或 DOM 元素,访问子组件 |
beforeUpdate | onBeforeUpdate | 未更新,获取更新前所有状态 |
updated | onUpdated | 获取更新后所有状态 |
beforeDestroy | onBeforeUnmount | 组件销毁之前 |
destroyed | onUnmounted | 组件销毁之后 |
提示
setup
是围绕 beforeCreate
和 created
生命周期钩子运行的,所以不需要显式地去定义。
Composition API
Vue2
是Options API
:一个逻辑会散乱在文件不同位置(data
、props
、computed
、watch
、生命周期钩子等),导致代码的可读性变差。当需要修改某个逻辑时,需要上下来回跳转文件位置。Vue3
是Composition API
:可将同一逻辑的内容写到一起,增强了代码的可读性、内聚性,其还提供了较为完美的逻辑复用性方案。所有逻辑在setup
函数中,使用ref
、watch
等函数组织代码
setup 函数
setup
函数是组合式 API
的入口函数,默认导出配置选项,setup
函数声明,返回模板需要数据与函数:
setup
函数是Vue3
特有的选项,作为组合式API
的起点- 从组件生命周期看,它在
beforeCreate
之前执行 - 函数中
this
不是组件实例,是undefined
- 如果数据或者函数在模板中使用,需要在
setup
返回 - 今后在
vue3
的项目中几乎用不到this
, 所有的东西通过函数获取。
响应式原理
原理
Vue2
响应式原理是利用es5
的Object.defineProperty()
对数据进行劫持结合发布订阅模式来实现Vue3
响应式原理是利用es6
的proxy
对数据代理,通过reactive()
函数给每一个对象都包一层proxy
,通过proxy
监听属性的变化,从而实现对数据的监控
Object.defineProperty 的缺陷
js
var obj = { _x: 1 };
Object.defineProperty(obj, "x", {
set: function (x) {
console.log("watch");
this._x = x;
},
get: function () {
return this._x;
},
});
obj.x = 11; // watch
console.log(obj.x); // 11
- 对象新增、删除属性没有响应式
- 数组新增、删除元素没有响应式
- 通过下标修改某个元素没有响应式
- 通过
.length
改变数组长度没有响应式 - 只有实例创建时
data
中有的数据实例创建后才是响应式的,给已创建好的vue
实例data
对象中添加属性时,数据虽然会更新,但视图不会更新,不具有响应式
Proxy 优势
js
var target = { a: 1 };
var proxy = new Proxy(target, {
set: function (target, key, value, receiver) {
console.log("watch");
return Reflect.set(target, key, value, receiver);
},
get: function (target, key, receiver) {
return target[key];
},
});
proxy.a = 11; // watch
console.log(target); // { a: 11 }
Proxy
性能整体上优于Object.defineProperty
Vue3
支持更多数据类型的劫持:Vue2
只支持Object
、Array
,Vue3
支持Object
、Array
、Map
、WeakMap
、Set
、WeakSet
)Vue3
支持更多时机来进行依赖收集和触发通知:Vue2
只在get
时进行依赖收集,Vue3
在get/has/iterate
时进行依赖收集;Vue2
只在set
时触发通知,Vue3
在set/add/delete/clear
时触发通知),所以Vue2
中的响应式缺陷Vue3
可以实现Vue3
做到了精准数据的数据劫持:Vue2
会把整个data
进行递归数据劫持,而Vue3
只有在用到某个对象时,才进行数据劫持,所以响应式更快并且占内存更小Vue3
的依赖收集器更容易维护:Vue3
监听和操作的是原生数组,Vue2
是通过重写的方法实现对数组的监控
reactive 函数和 ref 函数
reactive
函数:通常使用它复杂类型的响应式数据
- 从
vue
中导入reactive
函数 - 在
setup
函数中,使用reactive
函数,传入一个普通对象,返回一个响应式数据对象 - 最后
setup
函数返回一个对象,包含该响应式对象即可,模板中可使用
- ref 函数: 使用它定义响应式数据,不限类型
- 从
vue
中导入ref
函数 - 在
setup
函数中,使用ref
函数,传入普通数据,返回一个响应式数据 - 最后
setup
函数返回一个对象,包含该响应式数据即可 - 注意:使用
ref
创建的数据,js
中需要.value
,template
中可省略
- 如何抉择
reactive
可以转换对象成为响应式数据对象,但是不支持简单数据类型。ref
可以转换简单数据类型为响应式数据对象,也支持复杂数据类型,但是操作的时候需要.value
- 如果能确定数据是对象且字段名称也确定,可使用
reactive
转成响应式数据,其他一概使用ref
- 在定义响应式数据的函数选择上,遵循:尽量使用
ref
函数支持所有场景,确定字段的对象使用reactive
可以省去.value
TypeScript 的支持
Vue3
借鉴了 React Hook
实现了更自由的编程方式,提出了 Composition API
,Composition API
不需要通过指定一长串选项来定义组件,而是允许用户像编写函数一样自由地表达、组合和重用有状态的组件逻辑,同时提供出色的 TypeScript
支持。
打包体积变化
Vue2
官方说明运行时打包 23k
,但这只是没安装依赖的时候,随着依赖包和框架特性的增多,有时候不必要的,未使用的代码文件都被打包了进去,所以后期项目大了,打包文件会特别多还很大。
在 Vue3
中,通过将大多数全局 API
和内部帮助程序移动到 JavaScript
的 module.exports
属性上实现这一点,这允许现代模式下的 module bundler
能够静态地分析模块依赖关系,并删除与未使用的module.exports
属性相关的代码,模板编译器还生成了对 Tree Shaking
摇树优化友好的代码,只有在模板中实际使用某个特性时,该代码才导入该特性的帮助程序,尽管增加了许多新特性,但 Vue3
被压缩后的基线大小约为 10KB
,不到 Vue2
的一半。
其它小变化
Fragment(碎片)
:template
支持多个根节点。Teleport(传送门)
:Teleport
是一种能够将我们的模板移动到DOM
中Vue app
之外的其他位置的技术- 更好的
Tree-Shaking
支持:Vue 3
通过使用ES
模块来实现更好的Tree-Shaking
支持,从而减小了最终打包文件的大小。 Suspense
(悬念): 为处理异步组件和延迟加载提供了一种更简洁和直观的方式,通过使用<Suspense>
组件和v-slot
,我们可以更方便地管理加载状态、占位内容和错误处理- 重构了虚拟
DOM
:在编译时会将事件缓存、将slot
编译为lazy
函数、保存静态节点直接复用(静态提升)、以及添加静态标记、Diff
算法使用 最长递增子序列 优化了对比流程,使得虚拟DOM
生成速度大幅度提升 - 支持在
<style></style>
里使用v-bind
,给CSS
绑定JS
变量(color: v-bind(str)
)