什么是状态管理?
在开发 Vue 项目时,我们可能会遇到这样的问题:
-
组件之间共享数据困难(比如兄弟组件);
-
多个页面需要同步响应某个状态的变化(比如用户登录状态);
-
数据流混乱、难以维护和调试。
这时候我们就需要“状态管理”。
简单来说,状态管理就是在一个中心化的地方统一存储和管理应用的状态,并确保状态的变化是可预测的、可追踪的。
Vue 中有哪些状态管理方案?
| 状态管理方案 | 是否官方 | 特点 |
|---|---|---|
| props / emit | ✅ Vue 内置 | 父子组件传值,简单但不适合复杂场景 |
| provide / inject | ✅ Vue 内置 | 适用于层级较深组件传值 |
| Vuex | ✅ 官方(Vue 2/3 支持) | 经典状态管理方案,功能强大但语法稍显繁琐 |
| Pinia | ✅ Vue 3 推荐 | 新一代状态管理,轻量、组合式语法,替代 Vuex |
状态管理核心概念
无论是 Vuex 还是 Pinia,它们的核心概念都类似:
-
State(状态):存储共享数据的地方
-
Getter:对状态的计算属性(带缓存)
-
Mutation / Action:
-
Mutation(仅 Vuex):同步修改 state
-
Action:执行异步操作或复杂逻辑(可调用 mutation)
-
Vuex 示例(Vue 3)
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
1. 安装
yarn add vuex@next --save
# 或者使用npm
npm install vuex@next --save
2. 创建 store
// store/index.js
import { createStore } from 'vuex'
export default createStore({
state() {
return {
count: 0,
}
},
mutations: {
increment(state) {
state.count++
},
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
},
},
getters: {
doubleCount(state) {
return state.count * 2
},
},
})
3. 在 main.js 中挂载
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
createApp(App).use(store).mount('#app')
4. 在组件中使用
<template>
<div>
<p>count: {{ count }}</p>
<p>double: {{ doubleCount }}</p>
<button @click="increment">+1</button>
<button @click="asyncIncrement">异步 +1</button>
</div>
</template>
<script>
import { useStore } from 'vuex'
import { computed } from 'vue'
export default {
setup() {
const store = useStore()
const count = computed(() => store.state.count)
const doubleCount = computed(() => store.getters.doubleCount)
const increment = () => store.commit('increment')
const asyncIncrement = () => store.dispatch('asyncIncrement')
return { count, doubleCount, increment, asyncIncrement }
},
}
</script>
Pinia 示例(推荐)
Pinia 起始于 2019 年 11 月左右的一次实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。从那时起,我们就倾向于同时支持 Vue 2 和 Vue 3,并且不强制要求开发者使用组合式 API,我们的初心至今没有改变。
1. 安装
yarn add pinia
# 或者使用 npm
npm install pinia
2. 创建 store
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
async asyncIncrement() {
await new Promise((res) => setTimeout(res, 1000))
this.increment()
},
},
})
3. 在 main.js 中挂载
import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
4. 在组件中使用
<template>
<div>
<p>count: {{ count }}</p>
<p>double: {{ doubleCount }}</p>
<button @click="increment">+1</button>
<button @click="asyncIncrement">异步 +1</button>
</div>
</template>
<script setup>
import { useCounterStore } from './stores/counter'
const counter = useCounterStore()
const { count, doubleCount, increment, asyncIncrement } = counter
</script>
Vuex 与 Pinia 对比
| 特性 | Vuex | Pinia |
|---|---|---|
| 语法 | 传统风格(对象式) | 组合式 API,更灵活 |
| 支持模块化 | ✅ | ✅(推荐使用 defineStore) |
| 类型推导支持 | ❌ 支持不佳 | ✅ 原生支持 TypeScript |
| 体积 | 相对大 | 更轻量 |
| 推荐程度 | ✅(Vue 2项目) | ✅✅✅(Vue 3推荐) |
建议
-
如果在维护 Vue 2 项目,Vuex 仍然是主流选择。
-
如果使用 Vue 3,推荐使用 Pinia,语法更现代、学习成本低。
-
无论用哪个工具,掌握状态管理思想比工具更重要:状态集中管理、响应式、可预测性、调试方便。
Vue状态管理:Vuex与Pinia实战对比

1223

被折叠的 条评论
为什么被折叠?



