Composition API 简介
Vue 3 引入的 Composition API 是 Vue 生态系统中最重要的变革之一。它提供了一种更灵活、更强大的方式来组织和复用组件逻辑,特别适合处理复杂组件和大型应用。
Options API vs Composition API
Options API(传统方式)
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script>
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
},
decrement() {
this.count--
}
},
watch: {
count(newVal, oldVal) {
console.log(`Count changed from ${oldVal} to ${newVal}`)
}
},
mounted() {
console.log("Component mounted")
}
}
</script>
Composition API(现代方式)
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue'
// 响应式数据
const count = ref(0)
// 方法
const increment = () => {
count.value++
}
const decrement = () => {
count.value--
}
// 监听器
watch(count, (newVal, oldVal) => {
console.log(`Count changed from ${oldVal} to ${newVal}`)
})
// 生命周期钩子
onMounted(() => {
console.log("Component mounted")
})
</script>
核心响应式 API
1. ref – 创建响应式引用
import { ref } from 'vue'
// 基本类型
const count = ref(0)
console.log(count.value) // 0
count.value = 1
// 对象类型
const user = ref({
name: '张三',
age: 25
})
user.value.name = '李四'
2. reactive – 创建响应式对象
import { reactive } from 'vue'
const state = reactive({
count: 0,
user: {
name: '王五',
age: 30
},
items: ['item1', 'item2']
})
// 直接访问属性,不需要 .value
console.log(state.count) // 0
state.count = 1
state.items.push('item3')
3. computed – 计算属性
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(2)
// 计算总价
const total = computed(() => {
return price.value * quantity.value
})
console.log(total.value) // 200
// 可写的计算属性
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`
},
set(newValue) {
const [first, last] = newValue.split(' ')
firstName.value = first
lastName.value = last
}
})
4. watch 和 watchEffect – 监听器
import { ref, watch, watchEffect } from 'vue'
const count = ref(0)
const double = ref(0)
// watch - 精确监听
watch(count, (newVal, oldVal) => {
console.log(`Count changed: ${oldVal} → ${newVal}`)
double.value = newVal * 2
}, {
immediate: true, // 立即执行
deep: true // 深度监听
})
// watchEffect - 自动追踪依赖
watchEffect(() => {
console.log(`Count is: ${count.value}`)
// 自动追踪 count.value 的依赖
})
自定义组合函数
示例1:鼠标位置追踪
// useMouse.js
export function useMouse() {
import { ref, onMounted, onUnmounted } from 'vue'
const x = ref(0)
const y = ref(0)
const update = (event) => {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
// 在组件中使用
<script setup>
import { useMouse } from './useMouse'
const { x, y } = useMouse()
</script>
<template>
<div>Mouse position: {{ x }}, {{ y }}</div>
</template>
示例2:数据获取 Hook
// useFetch.js
export function useFetch(url) {
import { ref, onMounted } from 'vue'
const data = ref(null)
const loading = ref(true)
const error = ref(null)
const fetchData = async () => {
try {
loading.value = true
const response = await fetch(url)
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
data.value = await response.json()
} catch (e) {
error.value = e
} finally {
loading.value = false
}
}
onMounted(fetchData)
return {
data,
loading,
error,
refetch: fetchData
}
}
// 在组件中使用
<script setup>
import { useFetch } from './useFetch'
const { data, loading, error } = useFetch('https://api.example.com/users')
</script>
实际应用场景
场景1:表单处理
<script setup>
import { reactive, computed } from 'vue'
const form = reactive({
username: '',
email: '',
password: '',
confirmPassword: ''
})
const errors = reactive({})
// 表单验证
const isValid = computed(() => {
errors.username = form.username ? '' : '用户名不能为空'
errors.email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(form.email) ? '' : '邮箱格式不正确'
errors.password = form.password.length >= 6 ? '' : '密码至少6位'
errors.confirmPassword = form.password === form.confirmPassword ? '' : '两次密码不一致'
return !Object.values(errors).some(error => error)
})
const submit = () => {
if (isValid.value) {
console.log('表单提交:', form)
// 发送到API
}
}
</script>
场景2:状态管理
// store.js - 简单的状态管理
import { reactive } from 'vue'
export const store = reactive({
user: null,
token: null,
cart: [],
login(userData) {
this.user = userData.user
this.token = userData.token
localStorage.setItem('token', userData.token)
},
logout() {
this.user = null
this.token = null
localStorage.removeItem('token')
},
addToCart(item) {
this.cart.push(item)
},
removeFromCart(itemId) {
this.cart = this.cart.filter(item => item.id !== itemId)
}
})
// 在组件中使用
<script setup>
import { store } from './store'
const cartCount = computed(() => store.cart.length)
</script>
最佳实践
- 逻辑复用:将相关逻辑提取到自定义组合函数中
- 命名规范:组合函数以”use”开头,如 useUser、useFetch
- 单一职责:每个组合函数只关注一个特定的功能
- 类型安全:使用 TypeScript 获得更好的类型支持
- 性能优化:合理使用 computed 和 watch,避免不必要的重新计算
总结
Composition API 为 Vue 开发带来了革命性的变化。它提供了更灵活、更强大的代码组织方式,特别适合处理复杂组件和大型应用。通过自定义组合函数,我们可以实现逻辑的高度复用,提高代码的可维护性和可测试性。
虽然学习曲线比 Options API 稍陡,但一旦掌握,你会发现它能让你的 Vue 代码更加优雅和强大。建议在实际项目中逐步尝试 Composition API,从简单的组件开始,逐步应用到更复杂的场景中。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END




暂无评论内容