Vue 的选项式 API (Options API) 和组合式 API (Composition API) 是两种核心的代码组织方式,前者侧重 "按选项分类",后者侧重 "按逻辑分类",核心差异体现在设计理念、代码结构、复用性等维度,以下是全面对比和实用解读:
一、核心区别对比表
| 维度 | 选项式 API (Options API) | 组合式 API (Composition API) |
|---|---|---|
| 设计理念 | 按 "选项类型" 组织代码(data、methods、computed 等) | 按 "业务逻辑" 组织代码(同一逻辑的代码聚合) |
| 代码结构 | 分散式:同一逻辑的代码分散在不同选项中 | 聚合式:同一逻辑的代码集中在 setup 或 <script setup> |
| 适用场景 | 小型组件、简单业务(快速上手) | 中大型组件、复杂业务(逻辑复用 / 维护) |
| 逻辑复用 | 依赖 mixin(易命名冲突、来源不清晰) | 依赖组合式函数(Composables,纯函数复用,清晰可控) |
| 类型推导 | 对 TypeScript 支持弱(需手动标注) | 天然适配 TS,类型推导更完善 |
| 响应式写法 | 声明式:data 返回对象,Vue 自动响应式 | 手动式:用 ref/reactive 创建响应式数据 |
| 生命周期 | 直接声明钩子(created、mounted 等) | setup 中通过 onMounted 等函数调用(无 beforeCreate/created) |
| 代码可读性 | 简单场景清晰,复杂场景 "碎片化" | 复杂场景逻辑聚合,可读性更高 |
| 上手成本 | 低(符合传统前端思维) | 稍高(需理解 ref/reactive/setup 等概念) |
二、代码示例直观对比
1. 选项式 API(Vue 2/3 兼容)
xml
<template>
<div>{{ count }} <button @click="add">+1</button></div>
</template>
<script>
export default {
// 数据(响应式)
data() {
return {
count: 0
};
},
// 方法
methods: {
add() {
this.count++;
}
},
// 生命周期
mounted() {
console.log('组件挂载:', this.count);
}
};
</script>
特点:代码按 data/methods/mounted 等选项拆分,同一 "计数逻辑" 分散在不同区块。
2. 组合式 API(Vue 3 推荐,<script setup> 语法糖)
xml
<template>
<div>{{ count }} <button @click="add">+1</button></div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
// 响应式数据(ref 用于基本类型)
const count = ref(0);
// 方法(与数据聚合)
const add = () => {
count.value++; // ref 需通过 .value 访问
};
// 生命周期
onMounted(() => {
console.log('组件挂载:', count.value);
});
</script>
特点:"计数逻辑" 的数据、方法、生命周期全部聚合在一处,逻辑边界清晰。
三、核心差异深度解读
1. 逻辑复用:从 mixin 到 Composables(组合式函数)
-
选项式 API 的痛点(mixin) :复用逻辑需写 mixin 文件,多个 mixin 易出现命名冲突,且无法清晰知道属性来源:
javascript// mixin/countMixin.js export default { data() { return { count: 0 }; }, methods: { add() { this.count++; } } }; // 组件中使用 export default { mixins: [countMixin], // 引入后,count/add 混入组件,但来源不直观 }; -
组合式 API 的优势(Composables) :复用逻辑封装为纯函数,按需导入,属性来源清晰,无命名冲突:
javascript// composables/useCount.js import { ref } from 'vue'; export const useCount = () => { const count = ref(0); const add = () => count.value++; return { count, add }; }; // 组件中使用 <script setup> import { useCount } from './composables/useCount'; const { count, add } = useCount(); // 明确导入,来源清晰 </script>
2. 响应式原理:声明式 vs 手动式
- 选项式 API:
data返回的对象会被 Vue 递归劫持(Object.defineProperty/Proxy),自动变成响应式,直接通过this.xxx访问; - 组合式 API:需手动用
ref(基本类型)/reactive(引用类型)创建响应式数据,ref需通过.value访问(模板中自动解包),更灵活且可控。
3. 大型项目适配性
- 选项式 API:组件复杂度提升后,同一业务逻辑的代码会分散在
data/methods/computed/watch等多个选项中,形成 "面条代码",维护成本高; - 组合式 API:可将复杂业务拆分为多个 Composables(如
useUser/useCart/useOrder),每个函数负责一个逻辑模块,代码结构清晰,便于多人协作和维护。
四、选型建议
| 场景 | 推荐 API |
|---|---|
| 小型组件 / 快速原型 | 选项式 API |
| 中大型项目 / 复杂逻辑 | 组合式 API |
| 需兼容 Vue 2 + Vue 3 | 选项式 API(过渡) |
| 用 TypeScript 开发 | 组合式 API |
总结
- 选项式 API 是 "面向选项" 的思维,适合入门和简单场景,符合传统前端的代码组织习惯;
- 组合式 API 是 "面向逻辑" 的思维,解决了选项式 API 在复杂场景下的复用、维护痛点,是 Vue 3 的核心升级,也是大型项目的最佳实践。
两者并非互斥,Vue 3 完全兼容选项式 API,可根据项目规模和团队习惯灵活选择(甚至同一项目中混合使用)。