引言
Vue 3 的发布带来了革命性的变化,其中最引人注目的就是 Composition API 的引入。相比 Vue 2 中的 Options API,Composition API 提供了更加灵活和强大的方式来组织和复用逻辑代码。本文将深入探讨 Vue 3 Composition API 的核心概念、最佳实践以及在实际项目中的应用。
Vue 3 Composition API 核心概念
什么是 Composition API
Composition API 是 Vue 3 中引入的一种新的组件逻辑组织方式,它允许开发者以函数的形式组织和复用组件逻辑。与传统的 Options API 不同,Composition API 将组件的逻辑按照功能模块进行拆分,使得代码更加清晰、可维护。
// Vue 2 Options API 示例
export default {
data() {
return {
count: 0,
name: ''
}
},
methods: {
increment() {
this.count++
}
},
computed: {
reversedName() {
return this.name.split('').reverse().join('')
}
}
}
// Vue 3 Composition API 示例
import { ref, computed } from 'vue'
export default {
setup() {
const count = ref(0)
const name = ref('')
const increment = () => {
count.value++
}
const reversedName = computed(() => {
return name.value.split('').reverse().join('')
})
return {
count,
name,
increment,
reversedName
}
}
}
setup 函数
setup 是 Composition API 的入口函数,它在组件实例创建之前执行。在 setup 中,你可以访问组件的 props、context 以及定义响应式数据。
import { ref, reactive, watch, computed } from 'vue'
export default {
props: ['title'],
setup(props, context) {
// 访问 props
console.log(props.title)
// 定义响应式数据
const count = ref(0)
const user = reactive({ name: 'John', age: 30 })
// 计算属性
const doubledCount = computed(() => count.value * 2)
// 监听器
watch(count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`)
})
// 返回数据和方法供模板使用
return {
count,
user,
doubledCount
}
}
}
响应式数据处理
ref 和 reactive 的区别
在 Composition API 中,ref 和 reactive 是两种主要的响应式数据创建方式。
import { ref, reactive } from 'vue'
export default {
setup() {
// ref 用于基本类型数据
const count = ref(0)
const message = ref('Hello')
// reactive 用于对象类型数据
const user = reactive({
name: 'John',
age: 30,
address: {
city: 'New York',
country: 'USA'
}
})
// 访问 ref 数据需要使用 .value
const increment = () => {
count.value++
}
// reactive 数据可以直接访问
const updateName = (newName) => {
user.name = newName
}
return {
count,
message,
user,
increment,
updateName
}
}
}
深度响应式与浅层响应式
对于嵌套对象,Vue 3 默认提供深度响应式支持。但有时我们可能需要更精细的控制:
import { ref, reactive, shallowRef, toRefs } from 'vue'
export default {
setup() {
// 深度响应式
const deepObject = reactive({
nested: {
value: 1
}
})
// 浅层响应式
const shallowObject = shallowRef({
nested: {
value: 1
}
})
// 当更新浅层响应式对象的属性时,不会触发响应式更新
const updateNestedValue = () => {
// 这样不会触发响应式更新
shallowObject.value.nested.value = 2
// 这样会触发响应式更新
shallowObject.value = {
...shallowObject.value,
nested: {
value: 2
}
}
}
return {
deepObject,
shallowObject,
updateNestedValue
}
}
}
组合函数设计模式
创建可复用的组合函数
组合函数是 Composition API 的核心概念之一,它允许我们将逻辑封装成可复用的函数。
// composables/useCounter.js
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue)
const increment = () => {
count.value++
}
const decrement = () => {
count.value--
}
const reset = () => {
count.value = initialValue
}
const doubledCount = computed(() => count.value * 2)
return {
count,
increment,
decrement,
reset,
doubledCount
}
}
// composables/useFetch.js
import { ref, watch } from 'vue'
export function useFetch(url) {
const data = ref(null)
const loading = ref(false)
const error = ref(null)
const fetchData = async () => {
try {
loading.value = true
error.value = null
const response = await fetch(url)
data.value = await response.json()
} catch (err) {
error.value = err.message
} finally {
loading.value = false
}
}
// 自动执行一次
fetchData()
// 当 URL 变化时重新获取数据
watch(url, fetchData)
return {
data,
loading,
error,
refetch: fetchData
}
}
使用组合函数
// 在组件中使用组合函数
import { defineComponent } from 'vue'
import { useCounter } from '@/composables/useCounter'
import { useFetch } from '@/composables/useFetch'
export default defineComponent({
setup() {
// 使用计数器组合函数
const { count, increment, decrement, reset, doubledCount } = useCounter(10)
// 使用数据获取组合函数
const { data, loading, error, refetch } = useFetch('/api/users')
return {
count,
increment,
decrement,
reset,
doubledCount,
data,
loading,
error,
refetch
}
}
})
组件状态管理
全局状态管理
在 Vue 3 中,我们可以使用组合函数来创建全局状态管理:
// stores/userStore.js
import { reactive, readonly } from 'vue'
const state = reactive({
user: null,
isLoggedIn: false
})
const setUser = (userData) => {
state.user = userData
state.isLoggedIn = !!userData
}
const clearUser = () => {
state.user = null
state.isLoggedIn = false
}
export const useUserStore = () => {
return {
user: readonly(state.user),
isLoggedIn: readonly(state.isLoggedIn),
setUser,
clearUser
}
}
状态传递与通信
// 在组件中使用状态管理
import { defineComponent } from 'vue'
import { useUserStore } from '@/stores/userStore'
export default defineComponent({
setup() {
const { user, isLoggedIn, setUser, clearUser } = useUserStore()
const handleLogin = async () => {
try {
const response = await fetch('/api/login')
const userData = await response.json()
setUser(userData)
} catch (error) {
console.error('Login failed:', error)
}
}
const handleLogout = () => {
clearUser()
}
return {
user,
isLoggedIn,
handleLogin,
handleLogout
}
}
})
高级响应式编程技巧
响应式数据的解构与重构
import { ref, reactive, toRefs } from 'vue'
export default {
setup() {
// 使用 toRefs 进行解构
const state = reactive({
firstName: 'John',
lastName: 'Doe',
age: 30
})
const { firstName, lastName, age } = toRefs(state)
// 现在可以独立地监听每个属性
watch(firstName, (newVal) => {
console.log('First name changed:', newVal)
})
// 修改状态
const updateAge = (newAge) => {
state.age = newAge
}
return {
firstName,
lastName,
age,
updateAge
}
}
}
自定义响应式逻辑
// composables/useLocalStorage.js
import { ref, watch } from 'vue'
export function useLocalStorage(key, defaultValue) {
const storedValue = localStorage.getItem(key)
const value = ref(storedValue ? JSON.parse(storedValue) : defaultValue)
watch(value, (newValue) => {
localStorage.setItem(key, JSON.stringify(newValue))
}, { deep: true })
return value
}
// 使用自定义响应式逻辑
export default {
setup() {
const theme = useLocalStorage('theme', 'light')
const preferences = useLocalStorage('preferences', {})
return {
theme,
preferences
}
}
}
性能优化策略
避免不必要的计算
import { computed, ref } from 'vue'
export default {
setup() {
const items = ref([])
const filterText = ref('')
// 智能计算:只有当依赖发生变化时才重新计算
const filteredItems = computed(() => {
if (!filterText.value) return items.value
return items.value.filter(item =>
item.name.toLowerCase().includes(filterText.value.toLowerCase())
)
})
// 复杂计算的优化
const expensiveCalculation = computed({
get: () => {
// 只有当 items 或 filterText 改变时才重新计算
return items.value.reduce((acc, item) => acc + item.value, 0)
},
set: (newValue) => {
// 设置值的逻辑
}
})
return {
filteredItems,
expensiveCalculation
}
}
}
组件性能监控
// composables/usePerformance.js
import { ref, onMounted, onUnmounted } from 'vue'
export function usePerformance() {
const performanceData = ref({
renderTime: 0,
updateCount: 0
})
let startTime
const startTimer = () => {
startTime = performance.now()
}
const endTimer = () => {
if (startTime) {
performanceData.value.renderTime = performance.now() - startTime
performanceData.value.updateCount++
}
}
onMounted(() => {
console.log('Component mounted')
})
onUnmounted(() => {
console.log('Component unmounted')
})
return {
performanceData,
startTimer,
endTimer
}
}
实际项目应用案例
创建一个完整的用户管理系统
<template>
<div class="user-management">
<div class="header">
<h2>用户管理</h2>
<button @click="showAddForm = true">添加用户</button>
</div>
<!-- 添加用户表单 -->
<div v-if="showAddForm" class="form-overlay">
<form @submit.prevent="addUser">
<input v-model="newUser.name" placeholder="姓名" required />
<input v-model="newUser.email" type="email" placeholder="邮箱" required />
<button type="submit">添加</button>
<button type="button" @click="showAddForm = false">取消</button>
</form>
</div>
<!-- 用户列表 -->
<div class="user-list">
<div
v-for="user in filteredUsers"
:key="user.id"
class="user-item"
>
<span>{{ user.name }} - {{ user.email }}</span>
<button @click="deleteUser(user.id)">删除</button>
</div>
</div>
<!-- 加载状态 -->
<div v-if="loading">加载中...</div>
<!-- 错误处理 -->
<div v-if="error" class="error">{{ error }}</div>
</div>
</template>
<script>
import { defineComponent, ref, computed, watch } from 'vue'
import { useFetch } from '@/composables/useFetch'
export default defineComponent({
name: 'UserManagement',
setup() {
const showAddForm = ref(false)
const newUser = ref({ name: '', email: '' })
// 使用自定义组合函数获取用户数据
const { data: users, loading, error, refetch } = useFetch('/api/users')
// 过滤用户
const filterText = ref('')
const filteredUsers = computed(() => {
if (!filterText.value) return users.value || []
return (users.value || []).filter(user =>
user.name.toLowerCase().includes(filterText.value.toLowerCase()) ||
user.email.toLowerCase().includes(filterText.value.toLowerCase())
)
})
// 添加用户
const addUser = async () => {
try {
await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newUser.value)
})
newUser.value = { name: '', email: '' }
showAddForm.value = false
refetch() // 重新获取数据
} catch (err) {
console.error('添加用户失败:', err)
}
}
// 删除用户
const deleteUser = async (userId) => {
try {
await fetch(`/api/users/${userId}`, { method: 'DELETE' })
refetch() // 重新获取数据
} catch (err) {
console.error('删除用户失败:', err)
}
}
return {
showAddForm,
newUser,
users,
loading,
error,
filterText,
filteredUsers,
addUser,
deleteUser
}
}
})
</script>
<style scoped>
.user-management {
padding: 20px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.form-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.user-list {
margin-top: 20px;
}
.user-item {
display: flex;
justify-content: space-between;
padding: 10px;
border: 1px solid #ccc;
margin-bottom: 5px;
}
</style>
最佳实践总结
代码组织原则
- 功能分组:将相关的逻辑组织在一起
- 可复用性:提取通用逻辑为组合函数
- 清晰的接口:组合函数应该有明确的输入输出
- 类型安全:使用 TypeScript 提高代码质量
性能优化建议
- 合理使用计算属性:避免重复计算
- 细粒度响应式:只监听必要的数据变化
- 组件懒加载:对于大型组件使用动态导入
- 内存管理:及时清理监听器和定时器
开发工具支持
// 在开发环境中启用 Vue DevTools
import { defineComponent } from 'vue'
export default defineComponent({
name: 'MyComponent',
setup() {
// 启用调试信息
if (__DEV__) {
console.log('Development mode enabled')
}
return {}
}
})
结论
Vue 3 的 Composition API 为前端开发带来了革命性的变化。通过本文的详细介绍,我们看到了如何利用组合函数来组织代码、管理状态以及优化性能。Composition API 不仅提高了代码的可维护性和复用性,还为构建大型应用提供了更好的架构支持。
掌握这些最佳实践,可以帮助开发者构建更加健壮、高效的 Vue 应用程序。随着 Vue 3 的不断发展,我们期待看到更多基于 Composition API 的创新模式和工具出现,进一步提升前端开发的效率和质量。
记住,在实际项目中,要根据具体需求选择合适的 API 形式,并始终遵循代码可读性和维护性的原则。Composition API 的强大之处在于它提供了足够的灵活性,让开发者能够以最适合项目的方式组织代码。

评论 (0)