VUE的状态管理,VueX&Pinia
VueX
- 安装
- 创建
VueX的store、store/index.ts定义状态变更动作获取器
import { createStore} from 'vuex';
const store = createStore({
state:{
count:0,
},
// 一般处理同步操作
mutation:{
increment(state){
state.count++;
},
decrement(state){
state.count--;
},
},
// 异步的一些行为
action:{
increment({commit}){
commit('increment');
},
decrement({commit}){
commit('decrement');
},
},
getter:{
getCount(state){
return state.count
}
}
})
export default store- 引入
VueX
import {createApp} from 'vue';
import App from './App.vue';
import store from './store';
const app = createApp(App);
app.use(store);
app.mount('#app');- 组件中访问状态
mapState mapActions 简化状态和动作的访问
<template>
<div>
<p>count:{{count}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<!-- vue2写法 -->
<script>
import {mapState,mapActions} from 'vuex'
export default {
computed:{
...mapState(['count'])
},
methods:{
...mapActions(['increment','decrement'])
}
}
</script>
<!-- vue3写法 -->
<script setup lang='ts' name="xxxx">
import { useStore } from 'vuex'
import { computed, ref } from 'vue'
const store = useStore()
const count = computed(() => store.state.count)
const increment = () => store.dispatch('increment')
const decrement = () => store.dispatch('decrement')
</script>Pinia
- 安装
- 创建store,在src下创建一个stores文件夹,然后在里头创建各种store,方便根据业务逻辑进行管理,
stores/counter.ts
// options store 写法
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
// state 用 ref/reactive
const count = ref(0)
// getters 用 computed
const doubleCount = computed(() => count.value * 2)
// actions 就是普通函数
function increment(payload?: number) {
count.value += payload ?? 1
}
async function asyncIncrement(payload?: number) {
await new Promise(resolve => setTimeout(resolve, 1000))
increment(payload)
}
// 返回需要暴露的 state / getters / actions
return { count, doubleCount, increment, asyncIncrement }
})// Setup Store 写法 (composition API)
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
// state 用 ref/reactive
const count = ref(0)
// getters 用 computed
const doubleCount = computed(() => count.value * 2)
// actions 就是普通函数
function increment(payload?: number) {
count.value += payload ?? 1
}
async function asyncIncrement(payload?: number) {
await new Promise(resolve => setTimeout(resolve, 1000))
increment(payload)
}
// 返回需要暴露的 state / getters / actions
return { count, doubleCount, increment, asyncIncrement }
})- 注册在main.ts中
// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')- 使用
- 组件中使用
<!-- 组合式API -->
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="increment()">+1</button>
</div>
</template>
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'
const counter = useCounterStore()
// 方式一:直接用 store 实例访问,记得 state 是响应式的
console.log(counter.count)
counter.increment()
// 方式二:解构但保持响应性(必须用 storeToRefs)
const { count, doubleCount } = storeToRefs(counter)
// 解构 actions 可直接解构,无需 storeToRefs
const { increment, asyncIncrement } = counter
</script><!-- 选项式API -->
<script>
import { mapState, mapActions } from 'pinia'
import { useCounterStore } from '@/stores/counter'
export default {
computed: {
...mapState(useCounterStore, ['count', 'doubleCount']),
// 或者自定义名字
...mapState(useCounterStore, { myCount: 'count' })
},
methods: {
...mapActions(useCounterStore, ['increment', 'asyncIncrement'])
}
}
</script>- 跨Store使用
import { defineStore } from 'pinia'
import { useUserStore } from './user'
export const useCartStore = defineStore('cart', {
state: () => ({ items: [] }),
actions: {
checkout() {
const user = useUserStore() // 在 action 内部或外部都可以调用
if (!user.isLoggedIn) return
// ...
}
}
})- pinia为什么取代Vuex
- 去掉了 Mutation – 直接通过
counter.count++或 action 修改,代码更简洁。 - 完美的 TypeScript 支持 – 类型推断无需额外声明,写起来像原生 JS 一样顺滑。
- 无需
rootState/ 嵌套模块 – 每个 Store 都是独立的,通过相互引用代替模块嵌套。 - 支持 Devtools – Vue Devtools 原生支持 Pinia,可追踪 actions 和 state 变化。
- 热更新、插件扩展 – 轻松对接 SSR、持久化存储等。
vuex:状态、变更(同步)、动作(异步)和获取器分离