大家好,今天我们来聊聊在uni-app开发中一个绕不开的话题——全局状态管理。无论是用户信息、购物车数据,还是主题设置,一个优秀的状态管理方案能让你的应用逻辑更清晰、维护更轻松。这篇文章会从Vuex和Pinia两个主流方案入手,带大家全面了解如何在uni-app中优雅地管理全局状态。
一、为什么需要全局状态管理?
在复杂的uni-app项目中,我们经常会遇到多个页面、多个组件之间共享数据的场景。如果仅仅依靠页面传参或者事件总线(Event Bus),会导致:
数据流混乱:数据传来传去,难以追踪状态的变更源头。
组件耦合度高:组件之间直接依赖,复用性变差。
“状态地狱”:深层嵌套的组件传递状态,代码会变得异常繁琐。
全局状态管理库将所有共享状态抽离到一个全局的“仓库”(Store)中,任何组件都可以直接从中读取或修改状态,实现了数据的集中管理和响应式更新。
二、Vuex:经典永不过时
Vuex是Vue官方的状态管理库,成熟稳定,生态完善,在uni-app(Vue 2)项目中是首选方案。
1. 安装与配置
首先,在项目根目录下安装Vuex:
npm install vuex@3 --save然后,在项目main.js同级目录下创建store/index.js文件:
import Vue from'vue' import Vuex from'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { // 存放全局状态 userInfo: null, token: uni.getStorageSync('token') || '' }, mutations: { // 同步修改state的唯一方法 SET_USER_INFO(state, payload) { state.userInfo = payload }, SET_TOKEN(state, payload) { state.token = payload uni.setStorageSync('token', payload) } }, actions: { // 处理异步操作 async login({ commit }, credentials) { // 模拟API请求 const response = awaitnewPromise(resolve => { setTimeout(() => { resolve({ code: 0, data: { user: { name: 'uni-app-user', id: 1 }, token: 'fake-jwt-token-string' } }) }, 500) }) if (response.code === 0) { commit('SET_USER_INFO', response.data.user) commit('SET_TOKEN', response.data.token) returntrue } returnfalse } }, getters: { // state的计算属性 isLoggedIn: state => !!state.token, userName: state => state.userInfo ? state.userInfo.name : '游客' } }) exportdefault store最后,在main.js中挂载Store:
import store from './store' const app = new Vue({ store, ...App }) app.$mount()2. 在页面中使用
在页面或组件中,我们可以通过this.$store或者mapState、mapMutations等辅助函数来访问Store。
<template> <view> <text>用户:{{ userName }}</text> <button v-if="!isLoggedIn" @click="handleLogin">登录</button> </view> </template> <script> import { mapGetters, mapActions } from 'vuex' export default { computed: { ...mapGetters(['isLoggedIn', 'userName']) }, methods: { ...mapActions(['login']), async handleLogin() { const success = await this.login({ username: 'test', password: '123' }); if (success) { uni.showToast({ title: '登录成功' }); } } } } </script>三、Pinia:更轻量、更现代的选择
Pinia是Vue官方推荐的下一代状态管理库,它设计更简洁,对TypeScript支持更友好,并且在uni-app(Vue 3)项目中表现出色。
1. 安装与配置
首先,安装Pinia:
npm install pinia在main.js中引入并使用Pinia:
import { createSSRApp } from'vue' import { createPinia } from'pinia' import App from'./App.vue' exportfunction createApp() { const app = createSSRApp(App) app.use(createPinia()) return { app } }接着,创建你的Store文件,例如store/user.js:
import { defineStore } from'pinia' exportconst useUserStore = defineStore('user', { state: () => ({ userInfo: null, token: uni.getStorageSync('token') || '', }), getters: { isLoggedIn: (state) => !!state.token, userName: (state) => state.userInfo ? state.userInfo.name : '游客', }, actions: { async login(credentials) { // 模拟异步API请求 const response = awaitnewPromise(resolve => { setTimeout(() => { resolve({ code: 0, data: { user: { name: 'uni-app-user', id: 1 }, token: 'fake-jwt-token-string-pinia' } }) }, 500) }) if (response.code === 0) { this.userInfo = response.data.user this.token = response.data.token uni.setStorageSync('token', this.token) returntrue } returnfalse }, logout() { this.userInfo = null this.token = '' uni.removeStorageSync('token') } }, })2. 在页面中使用
Pinia的使用方式更加直观和简单。
<template> <view> <text>用户:{{ userStore.userName }}</text> <button v-if="!userStore.isLoggedIn" @click="handleLogin">登录</button> </view> </template> <script setup> import { useUserStore } from '@/store/user' const userStore = useUserStore() const handleLogin = async () => { const success = await userStore.login({ username: 'test', password: '123' }); if (success) { uni.showToast({ title: '登录成功' }); } } </script>四、实战经验总结
🎯 案例:用户登录状态持久化
背景:用户登录后,即使关闭小程序或App,下次打开时仍应保持登录状态。
问题:Store中的数据是内存中的,刷新后会丢失。
解决方案:
Vuex:在
SET_TOKENmutation中,同步使用uni.setStorageSync将token存入本地缓存。初始化state时,从uni.getStorageSync读取。Pinia:同样,在
loginaction中,获取到token后立即调用uni.setStorageSync。初始化state时直接从缓存读取。
结果:实现了登录状态的持久化。
踩坑记录:不要在action之外的地方修改本地缓存,保证状态的唯一数据源是Store。
五、常见问题解答
Q1:Vuex和Pinia应该怎么选?A:如果你的项目是基于Vue 2的uni-app,建议使用Vuex 3。如果是Vue 3,强烈推荐使用Pinia,它的API更简洁,类型推断更完善。
Q2:状态很多,Store文件会不会变得很大?A:会的。Vuex和Pinia都支持模块化(Modules),你可以将不同业务模块的状态拆分到不同的文件中,使代码结构更清晰。
六、注意事项
⚠️安全:不要在前端Store中存储任何敏感信息,如密码、密钥等。
⚠️命名:保持mutations(Vuex)和actions(Pinia)的命名清晰、规范,便于调试和追踪。
⚠️性能:对于非响应式或非常大的数据,避免直接放入state,以免造成不必要的性能开销。
写在最后
无论是Vuex还是Pinia,它们的核心思想都是将共享状态集中管理,让数据流变得可预测。掌握了它们,你就能更从容地应对复杂的uni-app应用开发。建议先收藏,再根据你的项目技术栈选择一个深入实践。