Vue 2 的响应式 API 和 Vue 3 的组合式 API 的详细对比,从核心机制、使用方式、代码示例及优缺点展开
以下是 Vue 2 的响应式 API 和 Vue 3 的组合式 API 的详细对比,从核心机制、使用方式、代码示例及优缺点展开:
 
1. Vue 2 的响应式 API
核心机制
- 基于 Object.defineProperty:- 通过劫持对象的 getter和setter实现数据变化追踪。
- 限制:无法检测属性的添加/删除,且不支持数组的某些变异操作(如直接修改索引 arr[0] = ...)。
 
- 通过劫持对象的 
主要 API
| 功能 | 实现方式 | 示例 | 
|---|---|---|
| 声明响应式数据 | data对象或Vue.set/this.$set添加属性 | ```javascript | 
| data() { return { count: 0 }; } ``` | 
              |
| 计算属性 | computed 对象 | javascript <br>computed: { fullName() { return this.firstName + this.lastName; } }<br>
 |
 | 侦听器 | watch 对象或 this.$watch 方法 | javascript <br>watch: {<br> count: (newVal) => console.log(newVal)<br>}<br>
 |
 | 方法 | methods 对象 | javascript <br>methods: { increment() { this.count++; } }<br>
 |
生命周期钩子
- 分散在 Options 中:如 created,mounted,beforeDestroy等。
2. Vue 3 的组合式 API
核心机制
- 基于 Proxy:- 全局响应式追踪,支持检测属性的增删改,且无需 Vue.set。
- 优势:更高效、更灵活,支持 for...in遍历和数组变异操作。
 
- 全局响应式追踪,支持检测属性的增删改,且无需 
核心函数
| 函数 | 用途 | 示例 | 
|---|---|---|
| reactive | 将对象转为响应式(返回 Proxy) | ```javascript | 
| const state = reactive({ count: 0 }); ``` | 
          |
| ref | 将基本类型转为响应式(返回一个 .value 对象) | javascript <br>const count = ref(0);<br>
 |
 | computed | 声明计算属性(返回响应式引用) | javascript <br>const fullName = computed(() => state.firstName + state.lastName);<br>
 |
 | watch | 监听数据变化(支持更灵活的选项) | javascript <br>watch(count, (newVal) => console.log(newVal));<br>
 |
 | onMounted | 生命周期钩子(组合式 API 形式) | javascript <br>onMounted(() => console.log('Mounted'));<br>
 |
核心函数对比
| 功能 | Vue 2 | Vue 3 | 说明 | 
|---|---|---|---|
| 响应式数据 | data对象 | reactive/ref | Vue 3 需显式声明响应式,支持更灵活的类型(对象/基本类型)。 | 
| 计算属性 | computed对象 | computed()函数 | Vue 3 需通过函数声明,返回值需手动返回到模板。 | 
| 侦听器 | watch对象 | watch()函数 | Vue 3 支持更灵活的选项(如 deep,immediate)。 | 
| 方法 | methods对象 | setup()返回函数 | Vue 3 在 setup()中定义方法并返回,无需this。 | 
3. 组合式 API 核心特性
(1) setup() 函数
 
- 入口点:所有逻辑集中在此函数中,替代 Options API 的分散选项。
- 执行时机:在 beforeCreate和created之前执行。
- 返回值:需返回一个对象,暴露给模板或子组件。
(2) ref vs reactive
 
| 函数 | 适用场景 | 示例 | 
|---|---|---|
| ref | 基本类型(如数字、字符串)或需要直接访问值的场景 | ```javascript | 
| const count = ref(0); console.log(count.value); ``` | ||
| reactive | 复杂对象(如对象、数组)或需要直接操作属性的场景 | ```javascript | 
| const state = reactive({ count: 0 }); console.log(state.count); ``` | ||
(3) 生命周期钩子
- 组合式形式:通过 onXXX前缀的函数声明(如onMounted,onBeforeUnmount)。
- 无需 this:直接在setup()中调用,无需通过this访问。
4. 代码示例对比
(1) 声明响应式数据
// Vue 2(Options API)
export default {data() {return { count: 0 };}
};// Vue 3(组合式 API)
import { ref } from 'vue';export default {setup() {const count = ref(0);return { count };}
};
(2) 计算属性
// Vue 2
export default {computed: {fullName() {return this.firstName + ' ' + this.lastName;}}
};// Vue 3
import { computed } from 'vue';export default {setup() {const state = reactive({firstName: 'John',lastName: 'Doe'});const fullName = computed(() => state.firstName + ' ' + state.lastName);return { fullName };}
};
(3) 生命周期
// Vue 2
export default {mounted() {console.log('Mounted');}
};// Vue 3
import { onMounted } from 'vue';export default {setup() {onMounted(() => console.log('Mounted'));return {};}
};
5. 对比总结表格
| 特性 | Vue 2 | Vue 3(组合式 API) | 优势/差异 | 
|---|---|---|---|
| 响应式核心 | Object.defineProperty | Proxy | Vue 3 支持属性增删和更灵活的数组操作。 | 
| 数据声明 | data对象 | reactive/ref显式声明 | Vue 3 需显式声明响应式,避免隐式问题。 | 
| 计算属性 | computed对象 | computed()函数 | Vue 3 更灵活,支持返回函数或对象。 | 
| 侦听器 | watch对象 | watch()函数 | Vue 3 支持更细粒度的选项(如 deep,flush)。 | 
| 方法 | methods对象 | setup()返回函数 | Vue 3 逻辑集中,减少 Options 耦合。 | 
| 生命周期钩子 | 分散在 Options 中 | onXXX函数集中声明 | Vue 3 钩子名更规范(如 onMounted),无需this。 | 
| 代码复用 | Mixins(易冲突) | 自定义组合函数(无污染) | 组合式 API 更易复用且避免命名冲突。 | 
| 模板绑定 | this.count | count(通过ref)或state.count(通过reactive) | Vue 3 需通过 ref.value或reactive对象访问值。 | 
6. 迁移建议
- 逐步迁移:在 Vue 2 项目中可通过 @vue/composition-api渐进式引入组合式 API。
- 优先使用组合式 API:在新项目中推荐使用组合式 API,因其更灵活、可维护。
- 注意 ref和reactive的区别:根据数据类型选择合适的方式声明响应式。
- 生命周期钩子替换:Vue 3 的 setup()会提前执行,需调整初始化逻辑顺序。
如需更详细示例,可参考 Vue 3 官方文档。
