Vue 2 的响应式 API 和 Vue 3 的组合式 API 的详细对比,从核心机制、使用方式、代码示例及优缺点展开

发布于:2025-05-01 ⋅ 阅读:(40) ⋅ 点赞:(0)

以下是 Vue 2 的响应式 API 和 Vue 3 的组合式 API 的详细对比,从核心机制、使用方式、代码示例及优缺点展开:
在这里插入图片描述


1. Vue 2 的响应式 API

核心机制
  • 基于 Object.defineProperty
    • 通过劫持对象的 gettersetter 实现数据变化追踪。
    • 限制:无法检测属性的添加/删除,且不支持数组的某些变异操作(如直接修改索引 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 的分散选项。
  • 执行时机:在 beforeCreatecreated 之前执行。
  • 返回值:需返回一个对象,暴露给模板或子组件。
(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.valuereactive 对象访问值。

6. 迁移建议

  1. 逐步迁移:在 Vue 2 项目中可通过 @vue/composition-api 渐进式引入组合式 API。
  2. 优先使用组合式 API:在新项目中推荐使用组合式 API,因其更灵活、可维护。
  3. 注意 refreactive 的区别:根据数据类型选择合适的方式声明响应式。
  4. 生命周期钩子替换:Vue 3 的 setup() 会提前执行,需调整初始化逻辑顺序。

如需更详细示例,可参考 Vue 3 官方文档