本文最后更新于 47 天前,其中的信息可能已经有所发展或是发生改变。
高可用|高性能|高可维护|生产级解决方案
🌟 核心优势
// 与传统Vuex对比
✅ 完整的TypeScript支持
✅ 更简洁直观的API设计
✅ 自动代码分割的模块化方案
✅ 0开销的响应式系统
✅ DevTools深度集成
🧱 模块化架构设计
/src
└── stores/
├── modules/
│ ├── user.store.ts # 用户相关状态
│ ├── product.store.ts # 商品管理状态
│ └── cart.store.ts # 购物车状态
├── shared/
│ └── api.ts # 公共API配置
└── index.ts # Store聚合入口
最佳实践:
// stores/modules/user.store.ts
export const useUserStore = defineStore('user', () => {
const userInfo = ref<Nullable<UserProfile>>(null)
const permissions = ref<string[]>([])
// 类型安全的Action
const fetchUserData = async (userId: string) => {
const { data } = await http.get<UserProfile>(`/api/users/${userId}`)
userInfo.value = data
}
return {
userInfo,
permissions,
fetchUserData
}
})
🔐 安全与持久化
// 持久化存储封装
import { Encryption } from 'crypto-js'
export function useSecureStorage(store: Store, keys: string[]) {
return persist(
store,
{
storage: {
getItem: (key) => {
const data = localStorage.getItem(key)
return data ? JSON.parse(Decrypt(data)) : null
},
setItem: (key, value) => {
localStorage.setItem(key, Encrypt(JSON.stringify(value)))
}
},
paths: keys
}
)
}
// Store使用
const useAuthStore = defineStore('auth', () => {
const token = ref('')
return { token }
})
useSecureStorage(useAuthStore, ['token']) // 仅加密存储token
🚀 性能优化策略
// 1. 请求缓存
const fetchProductList = cacheFn(async (categoryId: string) => {
return await http.get(`/products?category=${categoryId}`)
}, '10m') // 缓存10分钟
// 2. 自动取消重复请求
const { data } = await useFetch('/api/data', {
dedupe: 'defer' // 自动取消重复请求
})
// 3. 响应式数据优化
const heavyList = computed(() => {
return useHeavyDataProcessor(rawData.value)
}).skip(100) // 跳过非必要更新
🛠️ TypeScript深度集成
// 1. 泛型类型约束
interface Pagination<T> {
list: T[]
total: number
}
// 2. 复合类型Store
export const useProductStore = defineStore('products', () => {
const list = ref<ProductItem[]>([])
const pagination = reactive<Pagination<ProductItem>>({
list: [],
total: 0
})
return { list, pagination }
})
// 3. 类型推断增强
declare module 'pinia' {
export interface PiniaCustomProperties {
$encrypt: (data: string) => string
}
}
🔄 迁移策略(Vuex → Pinia)
// 渐进式迁移步骤:
1. 在新模块中使用Pinia
2. 使用适配器包装旧Vuex模块
class VuexModuleAdapter extends PiniaStore {
constructor(store) {
super(store)
}
}
3. 逐步重构核心模块
4. 最终移除Vuex依赖
📊 监控与错误处理
// 全局错误拦截
pinia.use(({ store }) => {
store.$onAction(({ name, after, onError }) => {
onError((error) => {
Sentry.captureException(error, {
extra: { store: store.$id, action: name }
})
})
after(() => {
Analytics.track(store.$id, name)
})
})
})
// 性能监控
const unsubscribe = store.$subscribe((mutation) => {
PerfMonitor.logStoreUpdate(mutation)
})
🧩 企业级规范
// .eslintrc.json
{
"rules": {
"pinia/no-actions-in-getters": "error",
"pinia/prefer-composition-api": "error",
"pinia/store-naming-convention": [
"error",
"^use[A-Z][a-zA-Z]+Store$"
]
}
}
📦 完整示例代码
// stores/enterprise.example.ts
export const useEnterpriseStore = defineStore('enterprise', () => {
const config = reactive<EnterpriseConfig>({
apiEndpoint: import.meta.env.VITE_API_URL,
maxConnections: 5
})
const { data, execute } = useAsyncData(
'enterprise-data',
() => $fetch(config.apiEndpoint),
{
server: false,
transform: (input) => EnterpriseDataSchema.parse(input)
}
)
return {
config,
data,
execute,
$reset: () => {
config.maxConnections = 5
data.value = null
}
}
})
📚 扩展阅读推荐
▶️ Vue3 官方文档
▶️ Pinia 实战指南
▶️ Vue Router 4