Vue2 和 Vue3 的区别
1. 响应式原理
- Vue2使用的是 ES5 的
Object.defineProperty
API 进行数据劫持并结合 发布-订阅模式 来实现的,它有一些缺陷,比如在某些情况下无法监听到数据发生的变化;而 Vue3 使用的是 ES6 的Proxy
API 实现响应式,与 Vue2 相比,Vue3解决了Vue2的无法监听对象property
的新增和删除,以及数组直接修改下标对应的元素或者修改数组的length
属性的问题。
2. 响应式数据
- Vue2 会递归地将
data
对象的property
转换为getter/setter
,也就是说,它基于原对象进行修改; - Vue3 不会修改原对象,而是修改原始对象的一个代理对象,因此无论何时访问
data
中的数据,都应该使用this
进行引用。
3. 生命周期
- 选项式 API:
beforeDestroy
改为了beforeUnmount
destroyed
改为了unmounted
- 组合式 API
onBeforeMount
onMounted
onBeforeUpdate
onUpdated
onBeforeUnmount
onUnmounted
4. 侦听器
- Vue3 的侦听器新增了一个配置项
flush: 'post'
,用于在侦听器的回调函数中访问到更新后的 DOM
5. 新增选项
expose: {Array}
:该选项用于限制父组件通过ref
对子组件模板引用的完全控制。emits: {Array | Object}
:该选项用于对组件要触发的事件进行显式声明,同时可以用于对触发的事件进行参数校验,通过返回一个布尔值来表明事件是否合法。
6. 指令变化
v-model
- Vue2 中的
v-model
被绑定在原生的input
元素上和子组件上时,都会在编译阶段展开为value
property 和change/input
事件 - Vue3 中的
v-model
绑定在原生的input
元素上时,会被展开为value
property 和change/input
事件,这一点和 Vue2 是一致的,但在被绑定在一个组件上时,情况则有所不同,它会被展开为modelValue
property 和update:modelValue
事件,并且这个命名可以通过v-model:title
进行修改。
- Vue2 中的
7. 组合式函数
- 组合式函数 是一个利用 Vue 的组合式 API 来封装和复用 有状态逻辑 的函数,它主要用于将组件中的单个或多个 逻辑关注点提取到一个单元中,由此解决了 Vue2 中的
vm.mixin()
API 所存在的一些问题:- 不清晰的数据来源:当使用了多个 mixin 时,实例上的数据属性来自哪个 mixin 变得不清晰,这使追溯实现和理解组件行为变得困难。这也是我们推荐在组合式函数中使用 ref + 解构模式的理由:让属性的来源在消费组件时一目了然。
- 命名空间冲突:多个来自不同作者的 mixin 可能会注册相同的属性名,造成命名冲突。若使用组合式函数,你可以通过在解构变量时对变量进行重命名来避免相同的键名。
- 隐式的跨 mixin 交流:多个 mixin 需要依赖共享的属性名来进行相互作用,这使得它们隐性地耦合在一起。而一个组合式函数的返回值可以作为另一个组合式函数的参数被传入,像普通函数那样。
- Vue3 不再推荐使用
vm.mixin()
,仅作为一个向下兼容的保留,你应该尽可能地使用 组合式函数 作为组件逻辑复用的最佳实践。
8. 内置组件
- 新增组件:
Teleport
:可以忽略 DOM 结构问题让模板挂载到任意的文档节点上,并且不影响模板的响应式动态更新,典型应用场景为:让模态框挂载到根节点上,以避免因节点优先级等问题导致模态框被更高优先级的 DOM 覆盖。Suspense
:实验性功能,它是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。