状态管理
Zap Admin Vue3使用Pinia作为状态管理方案,相比Vuex具有更好的TypeScript支持和更简洁的API。
Store的创建
在 src/stores/
目录下创建store文件:
// src/stores/user.js
import { defineStore } from 'pinia'
import { login, getUserInfo } from '@/api/user'
export const useUserStore = defineStore('user', {
state: () => ({
token: '',
userInfo: null,
permissions: []
}),
getters: {
isLoggedIn: (state) => !!state.token,
username: (state) => state.userInfo?.username,
avatar: (state) => state.userInfo?.avatar
},
actions: {
async login(credentials) {
try {
const { token } = await login(credentials)
this.token = token
// 获取用户信息
await this.fetchUserInfo()
} catch (error) {
throw error
}
},
async fetchUserInfo() {
try {
const data = await getUserInfo()
this.userInfo = data
this.permissions = data.permissions
} catch (error) {
throw error
}
},
logout() {
this.token = ''
this.userInfo = null
this.permissions = []
}
},
// 状态持久化
persist: {
enabled: true,
strategies: [
{
key: 'user',
storage: localStorage,
paths: ['token'] // 只持久化token
}
]
}
})
Store的使用
在组件中使用store:
// 在组件中使用
import { useUserStore } from '@/stores/user'
const UserProfile = defineComponent({
setup() {
const userStore = useUserStore()
// 使用state
const username = computed(() => userStore.username)
// 调用actions
const handleLogout = async () => {
await userStore.logout()
router.push('/login')
}
return {
username,
handleLogout
}
}
})
状态持久化
使用 pinia-plugin-persistedstate
实现状态持久化:
// src/stores/plugins/persist.js
import { createPersistedState } from 'pinia-plugin-persistedstate'
export const persist = createPersistedState({
key: prefix => `zap-admin-${prefix}`,
storage: window.localStorage,
// 序列化函数
serializer: {
serialize: JSON.stringify,
deserialize: JSON.parse
}
})
Store模块
应用配置Store
// src/stores/app.js
export const useAppStore = defineStore('app', {
state: () => ({
sidebar: {
opened: true,
withoutAnimation: false
},
device: 'desktop',
size: 'default',
theme: 'light'
}),
actions: {
toggleSidebar() {
this.sidebar.opened = !this.sidebar.opened
},
closeSidebar() {
this.sidebar.opened = false
},
toggleDevice(device) {
this.device = device
},
setSize(size) {
this.size = size
},
setTheme(theme) {
this.theme = theme
}
},
persist: {
enabled: true,
strategies: [
{
key: 'app',
paths: ['size', 'theme']
}
]
}
})
权限Store
// src/stores/permission.js
export const usePermissionStore = defineStore('permission', {
state: () => ({
routes: [],
addRoutes: [],
permissions: []
}),
getters: {
hasPermission: (state) => (permission) => {
return state.permissions.includes(permission)
}
},
actions: {
setRoutes(routes) {
this.addRoutes = routes
this.routes = constantRoutes.concat(routes)
},
setPermissions(permissions) {
this.permissions = permissions
}
}
})
最佳实践
- 按功能模块拆分store
- 使用TypeScript获得更好的类型提示
- 合理使用getters避免重复计算
- 在actions中处理异步逻辑
- 谨慎使用状态持久化,只持久化必要的数据
Store组织结构
src/stores/
├── modules/ # 功能模块store
│ ├── user.ts
│ ├── app.ts
│ └── permission.ts
├── plugins/ # store插件
│ └── persist.ts
└── index.ts # store入口文件