1. Vuex 的核心概念
Vuex 包含五个核心概念:
-
State:状态管理
-
Getters:计算属性
-
Mutations:同步修改状态
-
Actions:异步操作
-
Modules:模块化管理
2. 基础配置示例
// store/index.ts
import { createStore } from 'vuex'
import user from './modules/user'
import cart from './modules/cart'
export default createStore({
state: {
count: 0,
todos: []
},
getters: {
doneTodos: state => state.todos.filter(todo => todo.done),
getTodoById: state => id => state.todos.find(todo => todo.id === id)
},
mutations: {
INCREMENT(state, payload) {
state.count += payload.amount
},
SET_TODOS(state, todos) {
state.todos = todos
}
},
actions: {
async fetchTodos({ commit }) {
const response = await api.getTodos()
commit('SET_TODOS', response.data)
},
incrementAsync({ commit }, payload) {
setTimeout(() => {
commit('INCREMENT', payload)
}, 1000)
}
},
modules: {
user,
cart
}
})
3. 模块化示例
// store/modules/user.ts
interface UserState {
token: string | null;
userInfo: any;
}
export default {
namespaced: true,
state: (): UserState => ({
token: null,
userInfo: null
}),
getters: {
isLoggedIn: state => !!state.token,
username: state => state.userInfo?.name
},
mutations: {
SET_TOKEN(state, token: string) {
state.token = token
},
SET_USER_INFO(state, info: any) {
state.userInfo = info
}
},
actions: {
async login({ commit }, credentials) {
try {
const { token, user } = await api.login(credentials)
commit('SET_TOKEN', token)
commit('SET_USER_INFO', user)
return true
} catch (error) {
return false
}
},
async logout({ commit }) {
await api.logout()
commit('SET_TOKEN', null)
commit('SET_USER_INFO', null)
}
}
}
4. 组件中使用 Vuex
<template>
<div>
<p>Count: {{ count }}</p>
<p>Double Count: {{ doubleCount }}</p>
<p>Username: {{ username }}</p>
<button @click="increment">Increment</button>
<button @click="incrementAsync">Async Increment</button>
<button @click="logout">Logout</button>
<ul>
<li v-for="todo in doneTodos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
// State
const count = computed(() => store.state.count)
const username = computed(() => store.getters['user/username'])
// Getters
const doubleCount = computed(() => store.getters.doubleCount)
const doneTodos = computed(() => store.getters.doneTodos)
// Mutations & Actions
const increment = () => {
store.commit('INCREMENT', { amount: 1 })
}
const incrementAsync = () => {
store.dispatch('incrementAsync', { amount: 1 })
}
const logout = () => {
store.dispatch('user/logout')
}
</script>
5. 辅助函数使用
// 在 Options API 中使用
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
computed: {
// 映射 state
...mapState(['count']),
...mapState('user', ['userInfo']),
// 映射 getters
...mapGetters(['doneTodos']),
...mapGetters('user', ['isLoggedIn'])
},
methods: {
// 映射 mutations
...mapMutations(['INCREMENT']),
...mapMutations('user', ['SET_TOKEN']),
// 映射 actions
...mapActions(['fetchTodos']),
...mapActions('user', ['login', 'logout'])
}
}
6. 插件开发
// store/plugins/logger.ts
export default function createLogger() {
return store => {
store.subscribe((mutation, state) => {
console.log('mutation type:', mutation.type)
console.log('mutation payload:', mutation.payload)
console.log('current state:', state)
})
}
}
// store/index.ts
import createLogger from './plugins/logger'
export default createStore({
plugins: process.env.NODE_ENV !== 'production'
? [createLogger()]
: []
})
7. TypeScript 支持
// store/types.ts
export interface RootState {
count: number;
todos: Todo[];
}
export interface Todo {
id: number;
text: string;
done: boolean;
}
// store/index.ts
import { InjectionKey } from 'vue'
import { Store } from 'vuex'
import { RootState } from './types'
export const key: InjectionKey<Store<RootState>> = Symbol()
// main.ts
import { key } from './store'
app.use(store, key)
// 组件中使用
import { useStore } from 'vuex'
import { key } from '@/store'
const store = useStore(key)
要点:
1. Vuex 的使用场景:
-
多个组件共享状态
-
需要跨组件通信
-
复杂的状态管理
- Vuex 的优点:
-
集中式状态管理
-
可预测的状态变更
-
开发工具支持
-
模块化管理
- Mutations vs Actions:
-
Mutations 必须是同步函数
-
Actions 可以包含异步操作
-
Actions 通过提交 Mutation 修改状态
- 性能优化:
-
合理使用模块化
-
避免不必要的状态更新
-
使用 computed 缓存派生状态
- 调试技巧:
-
Vue DevTools
-
Vuex Logger 插件
-
严格模式