Skip to Content
Welcome to yujie-code-blogs build by Nextra 4.0 🎉
前端八股文合集VueVUE的状态管理,VueX & Pinia

VUE的状态管理,VueX&Pinia

VueX

  1. 安装
  2. 创建VueXstorestore/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
  1. 引入VueX
import {createApp} from 'vue'; import App from './App.vue'; import store from './store'; const app = createApp(App); app.use(store); app.mount('#app');
  1. 组件中访问状态

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

  1. 安装
  2. 创建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 } })
  1. 注册在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')
  1. 使用
  • 组件中使用
<!-- 组合式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 // ... } } })
  1. pinia为什么取代Vuex
  • 去掉了 Mutation – 直接通过 counter.count++ 或 action 修改,代码更简洁。
  • 完美的 TypeScript 支持 – 类型推断无需额外声明,写起来像原生 JS 一样顺滑。
  • 无需 rootState / 嵌套模块 – 每个 Store 都是独立的,通过相互引用代替模块嵌套。
  • 支持 Devtools – Vue Devtools 原生支持 Pinia,可追踪 actions 和 state 变化。
  • 热更新、插件扩展 – 轻松对接 SSR、持久化存储等。

vuex:状态、变更(同步)、动作(异步)和获取器分离