Vue 3 状态管理实战:用 Pinia 拆多 store、做持久化与调试

test12026-09-160 次阅读

为什么从 Vuex 切到 Pinia

Vue 3 项目里,Pinia 已经是官方推荐的状态方案。它去掉了 Vuex 里 mutations 这个冗余概念,state、getters、actions 直接对应,TypeScript 类型推断顺滑,store 之间是独立的模块,不需要用 namespace 层层嵌套。

一个最小可运行 store

下面用 setup 风格的 store 演示购物车场景:state 用 ref,派生数据用 computed,异步操作放 actions。

// stores/cart.ts
import { defineStore } from "pinia";
import { ref, computed } from "vue";

export const useCartStore = defineStore("cart", () => {
  const items = ref<{ id: number; name: string; price: number; qty: number }[]>([]);

  const total = computed(() =>
    items.value.reduce((sum, i) => sum + i.price * i.qty, 0)
  );

  function add(product: { id: number; name: string; price: number }) {
    const found = items.value.find((i) => i.id === product.id);
    if (found) found.qty += 1;
    else items.value.push({ ...product, qty: 1 });
  }

  async function checkout() {
    // 真实项目里这里发请求
    await new Promise((r) => setTimeout(r, 300));
    items.value = [];
  }

  return { items, total, add, checkout };
});

在组件里用

<script setup lang="ts">
import { useCartStore } from "./stores/cart";

const cart = useCartStore();
cart.add({ id: 1, name: "机械键盘", price: 399 });
</script>

<template>
  <p>共 {{ cart.items.length }} 件,合计 {{ cart.total }} 元</p>
  <button @click="cart.checkout()">结算</button>
</template>

按业务拆多个 store

  • 用户态 user store、购物车 cart store、UI 状态 ui store 分开定义,互不耦合,哪个页面用到再引入哪个。
  • 跨 store 调用很简单:在一个 store 的 action 里直接 import 另一个 store 的 useXxxStore() 即可,Pinia 自己管理实例化顺序。

持久化与调试

刷新后想保留购物车,用 pinia-plugin-persistedstate 一行配置即可写 localStorage,不需要自己监听 state 变化。

import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";

const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);

// store 里加一行开启
// export const useCartStore = defineStore("cart", () => { ... }, { persist: true });

调试时 Pinia 自带 devtools 支持,能直接看到每个 store 的状态变更时间线;开发环境建议给 action 加上 try/catch 并在失败时把错误抛到全局,方便定位是哪个 store 的动作出错。

T

test1

文章作者

为什么从 Vuex 切到 Pinia Vue 3 项目里,Pinia 已经是官方推荐的状态方案。它去掉了 Vuex 里...

分类
技术
发布时间
2026-09-16
字数
约 1982 字
阅读
0 次