前言
如果你刚开始学习 Vue 3,你可能会听到两个词:选项式 API 和 组合式 API。它们是什么?有什么区别?应该用哪个?这篇文章用最简单的方式讲清楚。
一、什么是选项式 API?
选项式 API 是 Vue 2 时代的经典写法,也是 Vue 3 仍然支持的写法。
特点:按类型分组
代码按照 data、methods、computed 等选项分类:
export default {
data() {
return {
count: 0,
name: '张三'
}
},
methods: {
add() {
this.count++
},
sayHi() {
console.log('我是' + this.name)
}
},
computed: {
double() {
return this.count * 2
}
},
mounted() {
console.log('组件挂载了')
}
}
关键点:
- ✅ 结构清晰,新手友好
- ✅ 每个选项有明确的用途
- ❌ 相关的代码被分散到不同位置
- ❌ 需要用
this访问数据
二、什么是组合式 API?
组合式 API 是 Vue 3 新增的写法,更灵活、更强大。
特点:按功能分组
相关的代码写在一起:
import { ref, computed, onMounted } from 'vue'
export default {
setup() {
// 计数相关功能
const count = ref(0)
const double = computed(() => count.value * 2)
const add = () => {
count.value++
}
// 用户信息相关功能
const name = ref('张三')
const sayHi = () => {
console.log('我是' + name.value)
}
// 生命周期
onMounted(() => {
console.log('组件挂载了')
})
return { count, double, add, name, sayHi }
}
}
更简洁的 <script setup> 写法(推荐):
<script setup>
import { ref, computed, onMounted } from 'vue'
// 计数相关功能
const count = ref(0)
const double = computed(() => count.value * 2)
const add = () => count.value++
// 用户信息相关功能
const name = ref('张三')
const sayHi = () => console.log('我是' + name.value)
// 生命周期
onMounted(() => console.log('组件挂载了'))
</script>
关键点:
- ✅ 相关代码组织在一起
- ✅ 不需要
this - ✅ 更容易复用逻辑(Composables)
- ❌ 需要理解响应式 API(ref、reactive)
三、核心区别:this 的使用
选项式 API:到处用 this
export default {
data() {
return {
name: '张三',
count: 0
}
},
methods: {
sayHi() {
// 必须用 this 访问 data
console.log(this.name)
},
add() {
// 必须用 this 访问其他数据
this.count++
}
}
}
为什么需要 this?
因为 data、methods、computed 写在不同的地方,它们之间需要 this 来连接。
组合式 API:不需要 this
import { ref } from 'vue'
export default {
setup() {
const name = ref('张三')
const count = ref(0)
const sayHi = () => {
// 直接用,不需要 this
console.log(name.value)
}
const add = () => {
// 直接用,不需要 this
count.value++
}
return { name, count, sayHi, add }
}
}
为什么不需要 this?
因为所有变量都在 setup() 函数的同一个作用域内,就像普通 JavaScript 一样直接使用。
四、生活比喻
选项式 API = 餐厅点餐
菜单分类:
- 前菜区
- 主菜区
- 甜品区
你需要的东西分散在不同区域
需要说"我要主菜区的牛排"
组合式 API = 自助餐
所有东西都在一个台子上
你可以自由组合:
- 牛排配薯条(相关的一组)
- 沙拉配汤(相关的一组)
需要什么直接拿
五、完整对比示例
示例:一个用户信息表单
选项式 API:
export default {
data() {
return {
form: {
username: '',
phone: '',
email: ''
},
loading: false,
rules: {
username: [{ required: true, message: '请输入用户名' }]
}
}
},
computed: {
isValid() {
return this.form.username && this.form.phone
}
},
methods: {
async submit() {
this.loading = true
// 提交逻辑...
this.loading = false
},
reset() {
this.form.username = ''
this.form.phone = ''
this.form.email = ''
}
}
}
组合式 API:
<script setup>
import { ref, computed } from 'vue'
// 表单数据
const form = ref({
username: '',
phone: '',
email: ''
})
// 表单验证规则
const rules = {
username: [{ required: true, message: '请输入用户名' }]
}
// 加载状态
const loading = ref(false)
// 计算属性
const isValid = computed(() => {
return form.value.username && form.value.phone
})
// 提交方法
const submit = async () => {
loading.value = true
// 提交逻辑...
loading.value = false
}
// 重置方法
const reset = () => {
form.value.username = ''
form.value.phone = ''
form.value.email = ''
}
</script>
六、优缺点对比
| 对比项 | 选项式 API | 组合式 API |
|---|---|---|
| 上手难度 | ⭐ 简单 | ⭐⭐⭐ 需要学习新概念 |
| 代码组织 | 按类型分组 | 按功能分组 |
| this 使用 | 到处需要 this | 不需要 this |
| 逻辑复用 | Mixins(容易冲突) | Composables(清晰) |
| TypeScript | 支持一般 | 支持很好 |
| 代码量 | 较多(boilerplate 多) | 较少 |
| 适合场景 | 简单组件、小项目 | 复杂逻辑、大项目 |
七、什么时候用哪个?
用选项式 API:
- ✅ 你刚学 Vue,想要简单易懂
- ✅ 组件逻辑简单,代码量少
- ✅ 团队成员更熟悉 Vue 2
用组合式 API:
- ✅ 项目复杂,逻辑多
- ✅ 需要复用逻辑(多个组件用同一套逻辑)
- ✅ 想要更好的 TypeScript 支持
- ✅ 新项目,没有历史包袱
八、实际项目例子
看看你项目中的代码:
stores/user.js(组合式 API)
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useUserStore = defineStore('user', () => {
// 状态
const user = ref({})
const token = ref("")
// 方法
function login(username, password) {
// ...
}
function logout() {
// ...
}
// 返回
return { user, token, login, logout }
})
为什么用组合式?
user、token、login、logout都是用户相关的功能- 放在一起,逻辑清晰
- 不需要
this.user、this.token,直接用
九、总结
核心区别一句话:
| 写法 | 特点 |
|---|---|
| 选项式 API | 代码按类型分类(data、methods 分开),用 this 连接 |
| 组合式 API | 代码按功能分类(相关的一起),不用 this |
我的建议:
- 新手:先学选项式 API,理解 Vue 的基本概念
- 进阶:转向组合式 API,享受更好的代码组织
- 新项目 :直接用组合式 API +
<script setup>
十、学习资源
有问题?欢迎留言讨论!