CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Vue 3 核心/课时/Pinia 状态管理
RawBlame
课时目录12 节

Vue 3 核心

  1. 01Vue 是什么
  2. 02项目创建与 SFC
  3. 03模板语法
  4. 04响应式基础
  5. 05组件与 Props
  6. 06计算属性与侦听
  7. 07组合式 API 深入
  8. 08Vue Router
  9. 09Pinia 状态管理
  10. 10数据获取
  11. 11构建与部署
  12. 12综合练习

Pinia 状态管理

store、actions、与 Redux 对照。

30 分钟

Pinia 状态管理

这一课你将能做到

  1. 用组合式写法定义 Pinia store,在组件中读写状态与 actions
  2. 用 storeToRefs 解构保持响应式
  3. 对照 Redux/React Context:何时需要全局 store,何时组件内 state 足够

为什么要学

跨页、跨组件共享的数据(当前用户、购物车、Todo 列表)若层层 props 会很烦。
Pinia 是 Vue 3 官方推荐的状态库,API 比早期 Vuex 轻。本站 React 侧常用局部 state + Context;学 Pinia 是为了读懂 Vue 中后台项目。

先建立图像

组件 A ──┐
组件 B ──┼─ useTodoStore() ──> 同一份 state
路由页 ──┘
概念人话
state全局记得的数据
getters类似 computed
actions改状态/异步的方法

跟着做

步骤 1:安装与注册

npm install pinia
import { createPinia } from "pinia";
app.use(createPinia());

create-vue 勾选则已就绪。

步骤 2:定义 store

// stores/todo.js
import { defineStore } from "pinia";
import { ref, computed } from "vue";

export const useTodoStore = defineStore("todo", () => {
  const items = ref([]);
  const filter = ref("all");

  const visible = computed(() => {
    if (filter.value === "active") return items.value.filter((t) => !t.done);
    if (filter.value === "done") return items.value.filter((t) => t.done);
    return items.value;
  });

  function add(text) {
    const t = text.trim();
    if (!t) return;
    items.value.push({ id: Date.now(), text: t, done: false });
  }

  function toggle(id) {
    const row = items.value.find((x) => x.id === id);
    if (row) row.done = !row.done;
  }

  return { items, filter, visible, add, toggle };
});

这是 setup store 风格,与组件组合式一致。

步骤 3:组件使用

<script setup>
import { storeToRefs } from "pinia";
import { useTodoStore } from "../stores/todo";

const store = useTodoStore();
const { visible, filter } = storeToRefs(store);
</script>

<template>
  <input
    @keyup.enter="
      store.add($event.target.value);
      $event.target.value = '';
    "
  />
  <button
    v-for="f in ['all', 'active', 'done']"
    :key="f"
    type="button"
    @click="filter = f"
  >
    {{ f }}
  </button>
  <ul>
    <li v-for="t in visible" :key="t.id">
      <label>
        <input type="checkbox" :checked="t.done" @change="store.toggle(t.id)" />
        {{ t.text }}
      </label>
    </li>
  </ul>
</template>

步骤 4:解构陷阱

const { items } = store; // 丢响应式
const { items } = storeToRefs(store); // 正确
store.add; // 方法可直接解构,不必 toRefs

步骤 5:持久化小练习

在 store 里 watch(items, …, { deep: true }) 写入 localStorage,启动时读回。
刷新后列表应还在——综合练习会用到。

步骤 6:对照 React

需求VueReact(本站常见)
全局客户端状态PiniaContext / 轻量库
服务端真相仍是 API仍是 Spring Boot
别把一切塞全局能本地就本地同

讲清楚要点

  1. Pinia 不是数据库:刷新默认清空,除非你持久化。
  2. 按领域拆 store:user/todo,避免上帝 store。
  3. 异步放 actions:先改 loading,再请求,再写数据。
  4. DevTools 可时间旅行调试,利于排错。
  5. SSR 需小心单例:入门 SPA 无妨。
  6. 与 Router 配合:守卫里读 useUserStore() 查登录态。

你可能会懵的地方

  • Vuex 还学吗?
    维护旧项目需要;新项目 Pinia。

  • options store 写法?
    state/getters/actions 对象形式仍支持;本课组合式优先。

  • 能直接改 state 吗?
    Pinia 允许;团队也可约定只走 actions,便于追踪。

  • 和 composable 重复?
    composable 可封装局部复用;跨树共享真相用 store。

  • Redux 样板多?
    对照时别被吓到;Pinia 更轻,思想都是「单一可预测状态」。

错法对照

错法问题正解
解构 store 丢响应UI 不更新storeToRefs
所有 UI 状态塞 Pinia难维护局部 ref 优先
在组件散落改深层结构无约定难审计集中 actions
把密钥放 store不安全密钥留服务端
多个 store 循环依赖初始化痛理清依赖或合并
当服务器数据缓存唯一方案过期难明确失效策略

自测三问

  1. 何时该用 Pinia 而不是组件内 ref?
  2. 为什么 storeToRefs 必要?
  3. Pinia 与后端 API 各自负责什么「真相」?

小结一句话

Pinia 用 store 共享客户端状态;组合式定义 + storeToRefs 使用,并与 React 全局状态方案对照理解。

官方延伸

  • Pinia 文档
  • 下一课:数据获取
加载本节练习…
← 上一课Vue Router下一课 →数据获取