1. 什么是狀態管理
狀態管理就是統一管理應用中的數據,讓數據在多個組件之間共享和同步。
// 沒有狀態管理 - 數據分散在各個組件中
// 組件A
const user = ref({ name: '張三', age: 25 })// 組件B
const user = ref({ name: '張三', age: 25 }) // 重復定義// 組件C
const user = ref({ name: '張三', age: 25 }) // 又是重復定義
// 有狀態管理 - 數據統一管理
// stores/user.ts
export const useUserStore = defineStore('user', () => {const user = ref({ name: '張三', age: 25 })return { user }
})// 所有組件都使用同一個數據源
const userStore = useUserStore()
2. 解決的核心問題
2.1 數據共享問題
<!-- 父組件 -->
<template><div><UserProfile :user="user" /><UserSettings :user="user" /><UserPosts :user="user" /></div>
</template><script setup>
// 需要把數據一層層傳遞下去
const user = ref({ name: '張三', age: 25 })
</script><!-- 子組件 -->
<template><div><h1>{{ user.name }}</h1><p>{{ user.age }}歲</p></div>
</template><script setup>
// 需要定義 props 接收數據
const props = defineProps(['user'])
</script>
使用狀態管理后:
<!-- 任何組件都可以直接訪問用戶數據 -->
<template><div><h1>{{ userStore.user.name }}</h1><p>{{ userStore.user.age }}歲</p></div>
</template><script setup>
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
</script>
2.2 數據同步問題
<!-- 組件A -->
<template><button @click="updateUser">更新用戶</button>
</template><script setup>
const updateUser = () => {user.name = '李四' // 只更新了組件A的數據
}
</script><!-- 組件B -->
<template><div>{{ user.name }}</div> <!-- 還是顯示"張三" -->
</template>
使用狀態管理后:
<!-- 組件A -->
<script setup>
const userStore = useUserStore()
const updateUser = () => {userStore.updateUser({ name: '李四' }) // 全局更新
}
</script><!-- 組件B -->
<template><div>{{ userStore.user.name }}</div> <!-- 自動顯示"李四" -->
</template>
3. 實際應用場景
3.1 用戶登錄狀態
// stores/auth.ts
export const useAuthStore = defineStore('auth', () => {const user = ref(null)const token = ref('')const isLoggedIn = computed(() => !!token.value)const login = async (credentials) => {const response = await api.login(credentials)token.value = response.tokenuser.value = response.userlocalStorage.setItem('token', response.token)}const logout = () => {token.value = ''user.value = nulllocalStorage.removeItem('token')}return { user, token, isLoggedIn, login, logout }
})
在組件中使用:
<!-- 導航欄 -->
<template><nav><div v-if="authStore.isLoggedIn">歡迎,{{ authStore.user.name }}<button @click="authStore.logout">退出</button></div><div v-else><button @click="showLogin = true">登錄</button></div></nav>
</template><script setup>
import { useAuthStore } from '@/stores/auth'
const authStore = useAuthStore()
</script>
3.2 購物車功能
// stores/cart.ts
export const useCartStore = defineStore('cart', () => {const items = ref([])const total = computed(() => items.value.reduce((sum, item) => sum + item.price * item.quantity, 0))const addItem = (product) => {const existingItem = items.value.find(item => item.id === product.id)if (existingItem) {existingItem.quantity++} else {items.value.push({ ...product, quantity: 1 })}}const removeItem = (id) => {items.value = items.value.filter(item => item.id !== id)}return { items, total, addItem, removeItem }
})
在多個組件中使用:
<!-- 商品列表 -->
<template><div v-for="product in products" :key="product.id"><h3>{{ product.name }}</h3><p>¥{{ product.price }}</p><button @click="cartStore.addItem(product)">加入購物車</button></div>
</template><!-- 購物車 -->
<template><div><h2>購物車 ({{ cartStore.items.length }})</h2><div v-for="item in cartStore.items" :key="item.id">{{ item.name }} × {{ item.quantity }} = ¥{{ item.price * item.quantity }}<button @click="cartStore.removeItem(item.id)">刪除</button></div><p>總計:¥{{ cartStore.total }}</p></div>
</template>
3.3 主題切換
// stores/theme.ts
export const useThemeStore = defineStore('theme', () => {const theme = ref('light')const toggleTheme = () => {theme.value = theme.value === 'light' ? 'dark' : 'light'document.documentElement.setAttribute('data-theme', theme.value)}return { theme, toggleTheme }
})
4. 狀態管理的優勢
4.1 數據集中管理
// 所有應用狀態都在一個地方
const appState = {user: { name: '張三', age: 25 },cart: { items: [], total: 0 },theme: 'light',loading: false
}
4.2 數據可預測
// 狀態變化都有明確的路徑
const updateUser = (newUser) => {// 只能通過這個函數更新用戶數據user.value = newUser
}
4.3 便于調試
// 可以追蹤所有狀態變化
const userStore = useUserStore()
console.log('當前用戶:', userStore.user)
console.log('是否登錄:', userStore.isLoggedIn)
4.4 代碼復用
// 多個組件可以復用相同的狀態邏輯
// 組件A
const { user, updateUser } = useUserStore()// 組件B
const { user, updateUser } = useUserStore()
5. 什么時候需要狀態管理
5.1 需要狀態管理的情況
- ? 多個組件需要共享數據
- ? 數據需要在組件間同步
- ? 應用狀態復雜,難以管理
- ? 需要持久化某些數據
- ? 需要調試狀態變化
5.2 不需要狀態管理的情況
- ? 簡單的單頁面應用
- ? 組件間沒有數據共享
- ? 數據只在單個組件內使用
- ? 應用規模很小
6. 狀態管理 vs 其他方案
6.1 Props 傳遞
<!-- 適合:簡單的父子組件通信 -->
<Parent><Child :data="parentData" />
</Parent>
6.2 Event Bus
// 適合:簡單的兄弟組件通信
import { mitt } from 'mitt'
const emitter = mitt()// 發送事件
emitter.emit('user-updated', newUser)// 監聽事件
emitter.on('user-updated', (user) => {console.log('用戶更新了:', user)
})
6.3 狀態管理
// 適合:復雜應用,多組件共享數據
const userStore = useUserStore()
7. 總結
狀態管理的核心作用是:
- 統一數據源 - 避免數據重復和不一致
- 簡化組件通信 - 不需要層層傳遞 props
- 提高代碼可維護性 - 數據邏輯集中管理
- 便于調試和測試 - 狀態變化可追蹤
- 支持數據持久化 - 可以保存到本地存儲
簡單來說:狀態管理就是讓應用的數據管理更加有序、可預測、易維護。