Composition API vs Options API
Vue3 两种组件写法的对比与选择
问题
Vue3 提供了 Composition API 和 Options API 两种组件写法,它们有什么区别?setup、ref、reactive、toRef 分别是什么?
解答
Options API
传统的 Vue2 写法,按选项类型组织代码:
export default {
data() {
return {
count: 0,
user: {
name: 'Tom',
age: 18
}
}
},
computed: {
doubleCount() {
return this.count * 2
}
},
methods: {
increment() {
this.count++
}
},
mounted() {
console.log('组件挂载完成')
}
}
Composition API
Vue3 新增的写法,按逻辑功能组织代码:
<script setup>
import { ref, reactive, computed, onMounted, toRef, toRefs } from 'vue'
// ref: 创建基本类型的响应式数据
const count = ref(0)
// reactive: 创建对象类型的响应式数据
const user = reactive({
name: 'Tom',
age: 18
})
// computed: 计算属性
const doubleCount = computed(() => count.value * 2)
// 方法直接定义
function increment() {
count.value++ // ref 需要 .value 访问
}
// toRef: 从 reactive 对象中提取单个属性,保持响应式
const name = toRef(user, 'name')
// toRefs: 解构 reactive 对象,保持每个属性的响应式
const { age } = toRefs(user)
// 生命周期
onMounted(() => {
console.log('组件挂载完成')
})
</script>
ref vs reactive
import { ref, reactive } from 'vue'
// ref: 适合基本类型,也可以包装对象
const count = ref(0)
const obj = ref({ a: 1 })
console.log(count.value) // 0
console.log(obj.value.a) // 1
// reactive: 只能用于对象类型
const state = reactive({
count: 0,
list: []
})
console.log(state.count) // 0,不需要 .value
toRef 和 toRefs 的作用
import { reactive, toRef, toRefs } from 'vue'
const user = reactive({
name: 'Tom',
age: 18
})
// 错误:直接解构会丢失响应式
const { name } = user // name 不是响应式的
// 正确:使用 toRef 提取单个属性
const name = toRef(user, 'name') // name 是响应式的
// 正确:使用 toRefs 解构整个对象
const { name, age } = toRefs(user) // 都是响应式的
// 修改会同步到原对象
name.value = 'Jerry'
console.log(user.name) // 'Jerry'
逻辑复用对比
Options API 使用 mixins,容易命名冲突:
// mixin
const counterMixin = {
data() {
return { count: 0 }
},
methods: {
increment() { this.count++ }
}
}
export default {
mixins: [counterMixin]
}
Composition API 使用组合函数,更清晰:
// useCounter.js
import { ref } from 'vue'
export function useCounter() {
const count = ref(0)
const increment = () => count.value++
return { count, increment }
}
// 组件中使用
import { useCounter } from './useCounter'
const { count, increment } = useCounter()
关键点
- ref 用于基本类型,访问需要
.value;reactive 用于对象类型,直接访问属性 - toRef/toRefs 解决 reactive 对象解构丢失响应式的问题
- Options API 按选项分类(data/methods/computed),Composition API 按功能逻辑组织
- Composition API 通过组合函数实现逻辑复用,比 mixins 更清晰,无命名冲突
<script setup>是 Composition API 的语法糖,更简洁
目录