Vue2与Vue3: 关键差异与新特性介绍
目录
1. Fragments、Teleport 和 createRenderer
一、Vue 2 与 Vue 3 的关键差异
1.双向数据绑定原理:
- Vue2:
使用Object.defineProperty() 对属性进行劫持,结合发布订阅模式实现数据响应
仅仅能监听属性,不支持对整个对象的监听,且不适用于数组
Object.defineProperty()
的作用
Object.defineProperty()
方法允许精确地添加或修改对象的属性。此方法接收三个参数:
- 要添加属性的对象。
- 属性的名称。
- 一个描述符对象,该对象指定了属性的值、可写性、可枚举性、可配置性等。
例如:
let data = { val: 0 };
Object.defineProperty(data, 'prop', {
get: function() {
return this.val;
},
set: function(newVal) {
this.val = newVal;
},
enumerable: true,
configurable: true
});
这个例子定义了一个名为 prop
的属性,它读取和设置内部 val
属性的值。
- Vue3:
采用ES6 Proxy API 对数据进行代理,实现更高效的数据监听
支持对对象和数组的监听,能够更细致地捕捉数据变化
Proxy API 简介
Proxy
是 ES6 引入的一种新的数据结构,它允许你创建一个对象的代理,从而在访问对象的属性或方法时进行拦截和自定义操作。Proxy
对象有两个参数:目标对象和处理器对象,处理器对象定义了当操作被执行时的自定义行为。
let target = { message: 'Hello' };
let handler = {
get(target, property, receiver) {
console.log(`Property ${property} has been read.`);
return Reflect.get(target, property, receiver);
},
set(target, property, value, receiver) {
console.log(`Property ${property} set to ${value}.`);
return Reflect.set(target, property, value, receiver);
}
};
let proxy = new Proxy(target, handler);
proxy.message; // Property message has been read.
proxy.message = 'Hi'; // Property message set to Hi.
2.支持碎片(Fragment)
- Vue2:不支持多个根节点
- Vue3:支持多个根节点,增加了组件的灵活性
为什么支持碎片很重要?
更自然的模板结构:开发者可以更自然地编写模板,而不必为了满足单一根节点的限制而进行额外的包装。
避免不必要的 DOM 操作:不需要额外的包装元素,减少了 DOM 操作和潜在的性能影响。
更好的组件封装:组件可以返回多个独立的 DOM 元素,使得组件的封装和复用更加灵活。
提高代码的可维护性:模板结构更清晰,有助于提高代码的可读性和可维护性。
如何实现的?
Vue 3 使用了 Fragment 指令来实现对多个根节点的支持。在编译阶段,Vue 3 会将多个根节点的模板编译为一个 Fragment 节点,然后在渲染过程中,将 Fragment 节点拆分为多个独立的 DOM 元素。
3.API类型
- Vue2:采用选项式API,将逻辑分割成data、computed、methods等部分
- Vue3:采用组合式API,提供更灵活的逻辑组织方式
4.数据变量和方法的定义
Vue2:数据通过data()函数定义,方法在 methods 对象中定义
Vue3:引入setup()函数作为组件的入口点,集中定义数据和方法
5.生命周期钩子
Vue 2 生命周期钩子
Vue 2 的生命周期钩子分为几个阶段:
-
创建阶段:
beforeCreate
:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。created
:在实例创建完成后被调用,此时,实例已完成数据观测、属性和方法的运算,$el
属性还未显示出来。
-
挂载阶段:
beforeMount
:在挂载开始之前被调用,相关的render
函数首次被调用。mounted
:在el
被新创建的vm.$el
替换,并挂载到实例上去之后调用该钩子,此时可以访问到 DOM 元素。
-
更新阶段:
beforeUpdate
:在数据变化之后,DOM 重新渲染之前调用,此时可以在这个钩子中进一步地更改状态。updated
:在由于数据更改导致的虚拟 DOM 重新渲染和打补丁后调用。
-
销毁阶段:
beforeDestroy
:在实例销毁之前调用,进行一些清理工作。destroyed
:在实例销毁后调用。
Vue 3 生命周期钩子
Vue 3 引入了 Composition API,带来了一组新的生命周期钩子,这些钩子在 setup
函数中使用:
-
创建阶段:
setup
:是 Composition API 的入口点,在组件实例创建之前执行,可以在这里声明响应式数据和函数。
-
挂载阶段:
onBeforeMount
:在挂载开始之前被调用,与 Vue 2 的beforeMount
钩子相对应。onMounted
:在组件第一次挂载到 DOM 后调用,与 Vue 2 的mounted
钩子相对应。
-
更新阶段:
onBeforeUpdate
:在更新开始之前被调用,与 Vue 2 的beforeUpdate
钩子相对应。onUpdated
:在组件更新 DOM 后调用,与 Vue 2 的updated
钩子相对应。
-
销毁阶段:
onBeforeUnmount
:在组件销毁之前调用,与 Vue 2 的beforeDestroy
钩子相对应。onUnmounted
:在组件销毁后调用,与 Vue 2 的destroyed
钩子相对应。
两者之间主要的区别:
1. 引入方式
-
Vue 2:
- 生命周期钩子是组件选项对象的一部分,不需要从外部引入。
-
Vue 3:
- 生命周期钩子函数需要从
vue
包中显式引入。 - 使用组合式 API 时,这些生命周期钩子作为函数导入并在
setup
函数内部使用。
- 生命周期钩子函数需要从
2. 使用场合
-
Vue 2:
- 生命周期钩子作为组件选项对象的属性来定义,例如
created()
,mounted()
, 等等。
- 生命周期钩子作为组件选项对象的属性来定义,例如
-
Vue 3:
- 在
setup
函数内部使用生命周期钩子,这是 Composition API 的一部分。
- 在
3. 响应式函数
-
Vue 2:
- 在
created
或beforeMount
钩子中定义的响应式数据和函数可以直接通过this
访问。
- 在
-
Vue 3:
- 在
setup
函数中定义的响应式数据和函数需要从setup
返回,以便在模板或其他 Composition API 钩子中使用。
- 在
4. 组合性
-
Vue 2:
- 选项式 API 中的生命周期钩子是分离的,每个钩子处理不同的逻辑。
-
Vue 3:
- 使用组合式 API 时,生命周期钩子可以与响应式状态、计算属性和其他函数一起组合在
setup
函数中。
- 使用组合式 API 时,生命周期钩子可以与响应式状态、计算属性和其他函数一起组合在
5. 生命周期顺序
- Vue 2 和 Vue 3:
- 生命周期的顺序和阶段在两者中保持一致,但是 Vue 3 引入了新的
setup
阶段,这是在beforeCreate
之前执行的。
- 生命周期的顺序和阶段在两者中保持一致,但是 Vue 3 引入了新的
6. 与模板的关系
-
Vue 2:
- 生命周期钩子中定义的响应式数据和函数自动与模板关联。
-
Vue 3:
- 在
setup
函数中返回的响应式数据和函数被模板使用。
- 在
6.父子传参
Vue 2 的父子传参
在 Vue 2 中,父子组件之间的参数传递主要依靠 props
和事件:
父传子(Props):
- 父组件通过
props
向子组件传递数据。 - 子组件通过声明
props
来接收来自父组件的数据。
// 子组件
export default {
props: ['message']
};
子传父(事件):
- 子组件使用
this.$emit
方法触发事件,并将数据传递给父组件。 - 父组件在子组件标签上监听这些事件
// 子组件
this.$emit('my-event', someData);
// 父组件
<ChildComponent @my-event="handleEvent"/>
Vue 3 的父子传参
Vue 3 保留了 Vue 2 的 props
和事件机制,但在组合式 API(setup
函数)中引入了 emit
函数,提供了一种新的方式来处理子组件向父组件传递数据:
-
父传子(Props):
与 Vue 2 类似,父组件通过props
向子组件传递数据。 -
子传父(事件):
在 Vue 3 的setup
函数中,emit
函数作为参数传入,可以直接使用,而不需要通过this.$emit
。
// 子组件
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup(props, { emit }) {
// 直接使用 emit 触发事件
function sendMessage() {
emit('my-event', 'Hello from child');
}
return { sendMessage };
}
});
- 父组件的事件监听方式不变,仍然使用
@event
语法。
// 父组件
<ChildComponent @my-event="handleEvent"/>
主要区别
- 子传父(组合式 API 中的 emit 函数):
- Vue 3 中的
setup
函数为子组件提供了一个新的emit
函数,使得事件触发更加直观和方便。 - 这种新的事件触发方式仅在组合式 API 中使用,选项式 API 中的事件触发方式与 Vue 2 相同。
- Vue 3 中的
7. 指令与插槽
- Vue 2:
slot
指令直接使用,v-for
优先级高于v-if
。 - Vue 3:
slot
指令需要使用v-slot
的形式,v-for
和v-if
可以更自然地结合使用。
8. main.js
文件的不同
- Vue 2:使用构造函数的形式创建 Vue 应用。
- Vue 3:使用工厂函数的形式,允许更灵活的应用创建方式。
二、Vue 3 的新特性
1. Fragments、Teleport 和 createRenderer
- Fragments:允许组件拥有多个根节点,增加了组件的灵活性。
- Teleport:能够将组件的某些部分传送到 DOM 中的其他位置,解决了 modals、toast 等元素的定位问题。
- createRenderer:提供了创建自定义渲染器的能力,可以将 Vue 的开发模型扩展到其他平台。
2. Composition API
Composition API 提供了一种更灵活、更易于维护的方式来组织组件逻辑,支持逻辑的复用。它包括 ref
、reactive
、computed
、watch
等响应式函数,以及 setup()
函数作为组件的入口点。
3. 更好的 TypeScript 支持
Vue 3 重写时考虑了 TypeScript 的支持,使得开发者能够享受到更好的类型推断和类型检查。
4. 性能提升
Vue 3 在虚拟 DOM 的重写、组件初始化和编译模板方面进行了优化,提高了性能。Vue 3 的响应式系统和组件初始化过程也得到了改进,使得组件更新更快。
5. 更易维护
Vue 3 的架构改进使得代码更易于维护,同时提供了更好的逻辑组合和复用。
三、非兼容变更
Vue 3 带来了一些非兼容的变更,如全局 API 的更改、模板指令的变化、组件定义方式的调整等。这些变更虽然可能需要开发者对现有代码进行调整,但它们旨在提供更好的性能和更灵活的用法。
四、移除的 API
Vue 3 移除了一些 Vue 2 的 API,如 keyCode 修饰符、$on
、$off
和 $once
实例方法、过滤器(filter)等。对于这些移除的 API,Vue 3 提供了替代方案,以帮助开发者平滑迁移。
五、总结
Vue 3 带来了许多令人兴奋的新特性和改进,包括组合式 API、更好的 TypeScript 支持、性能提升等。同时,它也进行了一些非兼容的变更和移除了一些 API。对于 Vue 开发者来说,Vue 3 提供了更多的可能性和更好的开发体验。
原文地址:https://blog.csdn.net/weixin_74009702/article/details/142722950
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!