在 uni-app 开发中,全局状态管理是一个高频面试考点,也是实际项目中绕不开的技术需求。无论是用户登录信息、购物车数据,还是应用级别的主题配置,都需要一套可靠的全局状态管理方案来支撑。本文将从面试的角度出发,系统梳理 uni-app 中实现全局状态管理的几种主流方式,帮助你从容应对这类问题。
为什么 uni-app 需要全局状态管理?
在单页面应用中,组件之间的数据传递可以通过 props 和 events 完成。但当应用规模扩大,跨页面、跨层级的组件通信变得频繁时,这种方式会变得极其繁琐且难以维护。全局状态管理的核心价值在于:提供一个集中式的数据存储,让任意组件都能读取和修改状态,同时保证数据变化的可追踪性。
uni-app 本身支持 Vue 和 Vue3 两种技术栈,因此全局状态管理的方案也需要分情况讨论。
方式一:Vuex(Vue2 技术栈)
Vuex 是 Vue 生态中最经典的全局状态管理库,在 uni-app 的 Vue2 项目中内置支持,无需额外安装。
基本使用步骤
1. 创建 store 文件
在项目根目录创建 store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
userInfo: null,
token: ''
},
mutations: {
SET_USER_INFO(state, payload) {
state.userInfo = payload
},
SET_TOKEN(state, payload) {
state.token = payload
}
},
actions: {
login({ commit }, userData) {
// 模拟登录请求
return new Promise((resolve) => {
setTimeout(() => {
commit('SET_USER_INFO', userData)
commit('SET_TOKEN', userData.token)
resolve()
}, 500)
})
}
},
getters: {
isLoggedIn: (state) => !!state.token
}
})
export default store
2. 在 main.js 中挂载
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.prototype.$store = store
const app = new Vue({
store,
...App
})
app.$mount()
3. 在组件中使用
computed: {
userInfo() {
return this.$store.state.userInfo
},
isLoggedIn() {
return this.$store.getters.isLoggedIn
}
},
methods: {
handleLogin() {
this.$store.dispatch('login', { name: '张三', token: 'abc123' })
}
}
面试加分点
- Vuex 的核心概念:State、Getter、Mutation、Action、Module,要能说清各自的职责和区别。
- Mutation 必须是同步函数,Action 可以包含异步操作,这是面试官常问的细节。
- 在 uni-app 中,Vuex 的 store 实例通过
Vue.prototype.$store挂载后,所有页面和组件都可以通过this.$store访问。
方式二:Pinia(Vue3 技术栈)
随着 uni-app 对 Vue3 的支持日趋完善,Pinia 已成为 Vue3 项目中的官方推荐状态管理方案。相比 Vuex,Pinia 的 API 更简洁,TypeScript 支持更好,且去掉了 Mutation 的概念。
基本使用步骤
1. 安装 Pinia
npm install pinia
2. 创建 store
// stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
token: ''
}),
getters: {
isLoggedIn: (state) => !!state.token
},
actions: {
async login(userData) {
// 模拟异步请求
this.userInfo = userData
this.token = userData.token
},
logout() {
this.userInfo = null
this.token = ''
}
}
})
3. 在 main.js 中注册
import { createSSRApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
export function createApp() {
const app = createSSRApp(App)
app.use(createPinia())
return { app }
}
4. 在组件中使用
import { useUserStore } from '@/stores/user'
export default {
setup() {
const userStore = useUserStore()
const handleLogin = async () => {
await userStore.login({ name: '张三', token: 'abc123' })
}
return { userStore, handleLogin }
}
}
面试加分点
- Pinia 去掉了 Mutation,Action 既可以是同步也可以是异步,简化了开发流程。
- Pinia 天然支持 TypeScript 类型推断,这在大型项目中是显著优势。
- Pinia 支持多个 store 实例,按模块拆分更加灵活。
方式三:全局事件总线(EventBus)
在小型项目中,如果不想引入 Vuex 或 Pinia,可以使用全局事件总线来实现简单的状态通信。
// main.js
Vue.prototype.$bus = new Vue()
// 组件 A:发送事件
this.$bus.$emit('updateUser', { name: '张三' })
// 组件 B:监听事件
mounted() {
this.$bus.$on('updateUser', (data) => {
this.userInfo = data
})
},
beforeDestroy() {
this.$bus.$off('updateUser')
}
缺点:数据流向不清晰,难以追踪状态变化,不适合中大型项目。面试中如果提到这种方式,要能指出它的局限性。
方式四:globalData + 本地存储
uni-app 提供了 getApp() 方法,可以获取全局应用实例,通过挂载自定义属性实现简单的全局状态。
// App.vue
export default {
globalData: {
userInfo: null,
token: ''
}
}
// 任意页面
const app = getApp()
app.globalData.token = 'abc123'
配合 uni.setStorageSync 和 uni.getStorageSync,可以实现状态的持久化。这种方式适合极简场景,但缺乏响应式更新能力。
各方案对比与选型建议
| 方案 | 适用场景 | 响应式 | 持久化 | 学习成本 |
|---|---|---|---|---|
| Vuex | Vue2 项目 | 支持 | 需插件 | 中等 |
| Pinia | Vue3 项目 | 支持 | 需插件 | 低 |
| EventBus | 小型项目 | 手动 | 不支持 | 低 |
| globalData | 极简场景 | 不支持 | 手动 | 低 |
选型建议:Vue2 项目优先使用 Vuex,Vue3 项目优先使用 Pinia。如果项目规模很小,globalData 配合本地存储也能满足需求。
面试回答思路总结
当面试官问到“uni-app 中如何实现全局状态管理”时,建议按以下结构回答:
- 先分技术栈:说明 Vue2 用 Vuex,Vue3 用 Pinia,体现你对 uni-app 双技术栈的了解。
- 再讲原理:简要说明所选方案的核心概念(如 State、Mutation、Action)。
- 结合实际:举例说明在项目中如何用全局状态管理处理登录态、购物车等场景。
- 对比补充:提一下 EventBus 和 globalData 等轻量方案,并说明各自适用场景。
这样的回答既有广度又有深度,能够充分展示你的技术视野和实战经验。
未经允许不得转载:任鹏个人博客 » uniapp 面试题:uni-app 中如何实现全局状态管理?

