目录
- 前言
- Pinia 简介
- 环境准备与安装 - 3.1 Vue3 项目初始化
- 3.2 安装 Pinia
 
- 创建第一个 Store - 4.1 定义 Store 文件结构
- 4.2 defineStore详解
- 4.3 ASCII 图解:响应式状态流动
 
- 在组件中使用 Pinia - 5.1 根应用挂载 Pinia
- 5.2 组件内调用 Store
- 5.3 响应式更新示例
 
- Getters 与 Actions 深度解析 - 6.1 Getters(计算属性)的使用场景
- 6.2 Actions(方法)的使用场景
- 6.3 异步 Action 与 API 请求
 
- 模块化与多 Store 管理 - 7.1 多个 Store 的组织方式
- 7.2 互相调用与组合 Store
 
- 插件与持久化策略 - 8.1 Pinia 插件机制简介
- 8.2 使用 pinia-plugin-persistedstate实现持久化
- 8.3 自定义简单持久化方案示例
 
- Pinia Devtools 调试 
- 实战示例:Todo List 应用 - 10.1 项目目录与功能描述
- 10.2 编写 useTodoStore
- 10.3 组件实现:添加、删除、标记完成
- 10.4 整体数据流动图解
 
- 高级用法:组合 Store 与插件扩展 - 11.1 组合式 Store:useCounter调用useTodo
- 11.2 自定义插件示例:日志打印插件
 
- 总结
前言
在 Vue3 中,Pinia 已经正式取代了 Vuex,成为官方推荐的状态管理工具。Pinia 以“轻量、直观、类型安全”为目标,通过 Composition API 的方式定义和使用 Store,不仅上手更快,还能借助 TypeScript 获得良好体验。本文将从安装与配置入手,结合代码示例与图解,深入讲解 Pinia 各项核心功能,帮助你在实际项目中快速掌握状态管理全流程。
Pinia 简介
- 什么是 Pinia:Pinia 是 Vue3 的状态管理库,类似于 Vuex,但接口更简洁,使用 Composition API 定义 Store,无需繁重的模块结构。
- 核心特点: - 基于 Composition API:使用 defineStore定义,返回函数式 API,易于逻辑复用;
- 响应式状态:Store 内部状态用 ref/reactive管理,组件通过直接引用或解构获取响应式值;
- 轻量快速:打包后体积小,无复杂插件系统;
- 类型安全:与 TypeScript 一起使用时,可自动推导 state、getters、actions 的类型;
- 插件机制:支持持久化、订阅、日志等插件扩展。
 
环境准备与安装
3.1 Vue3 项目初始化
可依据个人偏好选用 Vite 或 Vue CLI,此处以 Vite 为例:
# 初始化 Vue3 + Vite 项目
npm create vite@latest vue3-pinia-demo -- --template vue
cd vue3-pinia-demo
npm install
此时项目目录类似:
vue3-pinia-demo/
├─ index.html
├─ package.json
├─ src/
│  ├─ main.js
│  ├─ App.vue
│  └─ assets/
└─ vite.config.js
3.2 安装 Pinia
在项目根目录运行:
npm install pinia
安装完成后,即可在 Vue 应用中引入并使用。
创建第一个 Store
4.1 定义 Store 文件结构
建议在 src 下新建 stores 或 store 目录,用于集中存放所有 Store 文件。例如:
src/
├─ stores/
│  └─ counterStore.js
├─ main.js
├─ App.vue
...
4.2 defineStore 详解
在 src/stores/counterStore.js 编写第一个简单计数 Store:
// src/stores/counterStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useCounterStore = defineStore('counter', () => {
  // 1. state:使用 ref 定义响应式变量
  const count = ref(0);
  // 2. getters:定义计算属性
  const doubleCount = computed(() => count.value * 2);
  // 3. actions:定义方法,可同步或异步
  function increment() {
    count.value++;
  }
  function incrementBy(amount) {
    count.value += amount;
  }
  return {
    count,
    doubleCount,
    increment,
    incrementBy
  };
});
- defineStore('counter', () => { ... }):第一个参数为 Store 唯一 id(- counter),第二个参数是一个“setup 函数”,返回需要暴露的状态、计算属性和方法。
- 状态 count:使用ref定义,组件读取时可直接响应。
- 计算属性 doubleCount:使用computed,自动根据count更新。
- 方法 increment、incrementBy:对状态进行更改。
4.3 ASCII 图解:响应式状态流动
┌───────────────────────────┐
│     useCounterStore()     │
│ ┌────────┐  ┌───────────┐ │
│ │ count  │→ │ increment │ │
│ │  ref   │  └───────────┘ │
│ └────────┘   ┌──────────┐ │
│               │ double  │ │
│               │ Count   │ │
│               └──────────┘ │
└───────────────────────────┘
组件 ←─── 读取 count / doubleCount ───→ 自动更新
组件 ── 调用 increment() ──▶ count.value++
- 组件挂载时,调用 useCounterStore()拿到同一个 Store 实例,读取count或doubleCount时会自动收集依赖;
- 当调用 increment()修改count.value,Vue 的响应式系统会通知所有依赖该值的组件重新渲染。
在组件中使用 Pinia
5.1 根应用挂载 Pinia
在 src/main.js(或 main.ts)中引入并挂载 Pinia:
// src/main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app');
这一步让整个应用具备了 Pinia 的能力,后续组件调用 useCounterStore 时,都能拿到相同的 Store 实例。
5.2 组件内调用 Store
在任意组件里,使用如下方式获取并操作 Store:
<!-- src/components/CounterDisplay.vue -->
<template>
  <div>
    <p>当前计数:{{ count }}</p>
    <p>双倍计数:{{ doubleCount }}</p>
    <button @click="increment">+1</button>
    <button @click="incrementBy(5)">+5</button>
  </div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counterStore';
// 1. 取得 Store 实例
const counterStore = useCounterStore();
// 2. 从 Store 解构需要的部分
const { count, doubleCount, increment, incrementBy } = counterStore;
</script>
<style scoped>
button {
  margin-right: 8px;
}
</style>
- 组件渲染时,count、doubleCount自动读取 Store 中的响应式值;
- 点击按钮时,调用 increment()或incrementBy(5)修改状态,UI 自动更新。
5.3 响应式更新示例
当另一个组件也引用同一 Store:
<!-- src/components/CounterLogger.vue -->
<template>
  <div>最新 count:{{ count }}</div>
</template>
<script setup>
import { watch } from 'vue';
import { useCounterStore } from '@/stores/counterStore';
const counterStore = useCounterStore();
const { count } = counterStore;
// 监听 count 变化,输出日志
watch(count, (newVal) => {
  console.log('count 变为:', newVal);
});
</script>
- 无论是在 CounterDisplay还是其他组件里调用increment(),CounterLogger中的count都会随着变化而自动触发watch。
Getters 与 Actions 深度解析
6.1 Getters(计算属性)的使用场景
- 用途:将复杂的计算逻辑从组件中抽离,放在 Store 中统一管理,并保持惟一数据源。
- 示例:假设我们有一个待办列表,需要根据状态计算未完成数量:
// src/stores/todoStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useTodoStore = defineStore('todo', () => {
  const todos = ref([
    { id: 1, text: '学习 Pinia', done: false },
    { id: 2, text: '写单元测试', done: true }
  ]);
  // 计算属性:未完成条目
  const incompleteCount = computed(() =>
    todos.value.filter((t) => !t.done).length
  );
  return { todos, incompleteCount };
});
- 组件中直接读取 incompleteCount即可,且当todos更新时会自动重新计算。
6.2 Actions(方法)的使用场景
- 用途:封装修改 state 或执行异步逻辑的函数。
- 同步 Action 示例:添加/删除待办项
// src/stores/todoStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useTodoStore = defineStore('todo', () => {
  const todos = ref([]);
  function addTodo(text) {
    todos.value.push({ id: Date.now(), text, done: false });
  }
  function removeTodo(id) {
    todos.value = todos.value.filter((t) => t.id !== id);
  }
  function toggleTodo(id) {
    const item = todos.value.find((t) => t.id === id);
    if (item) item.done = !item.done;
  }
  const incompleteCount = computed(() =>
    todos.value.filter((t) => !t.done).length
  );
  return { todos, incompleteCount, addTodo, removeTodo, toggleTodo };
});
// src/stores/todoStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import axios from 'axios';
export const useTodoStore = defineStore('todo', () => {
  const todos = ref([]);
  const loading = ref(false);
  const error = ref('');
  async function fetchTodos() {
    loading.value = true;
    error.value = '';
    try {
      const res = await axios.get('/api/todos');
      todos.value = res.data;
    } catch (e) {
      error.value = '加载失败';
    } finally {
      loading.value = false;
    }
  }
  const incompleteCount = computed(() =>
    todos.value.filter((t) => !t.done).length
  );
  return { todos, incompleteCount, loading, error, fetchTodos };
});
- 组件中调用 await todoStore.fetchTodos()即可触发异步加载,并通过loading/error跟踪状态。
6.3 异步 Action 与 API 请求
组件中使用示例:
<!-- src/components/TodoList.vue -->
<template>
  <div>
    <button @click="load">加载待办</button>
    <div v-if="loading">加载中...</div>
    <div v-else-if="error">{{ error }}</div>
    <ul v-else>
      <li v-for="item in todos" :key="item.id">
        <span :class="{ done: item.done }">{{ item.text }}</span>
        <button @click="toggle(item.id)">切换</button>
        <button @click="remove(item.id)">删除</button>
      </li>
    </ul>
    <p>未完成:{{ incompleteCount }}</p>
  </div>
</template>
<script setup>
import { onMounted } from 'vue';
import { useTodoStore } from '@/stores/todoStore';
const todoStore = useTodoStore();
const { todos, loading, error, incompleteCount, fetchTodos, toggleTodo, removeTodo } = todoStore;
function load() {
  fetchTodos();
}
function toggle(id) {
  toggleTodo(id);
}
function remove(id) {
  removeTodo(id);
}
// 组件挂载时自动加载
onMounted(() => {
  fetchTodos();
});
</script>
<style scoped>
.done {
  text-decoration: line-through;
}
</style>
- 组件以 onMounted调用异步 ActionfetchTodos(),并通过解构获取loading、error、todos、incompleteCount。
- 按钮点击调用同步 Action toggleTodo(id)、removeTodo(id)。
模块化与多 Store 管理
7.1 多个 Store 的组织方式
对于大型项目,需要将状态拆分成多个子模块,各司其职。例如:
src/
├─ stores/
│  ├─ todoStore.js
│  ├─ userStore.js
│  └─ cartStore.js
- userStore.js管理用户信息:登录、登出、权限等
- cartStore.js管理购物车:添加/删除商品、计算总价
示例:userStore.js
// src/stores/userStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useUserStore = defineStore('user', () => {
  const userInfo = ref({ name: '', token: '' });
  const isLoggedIn = computed(() => !!userInfo.value.token);
  function login(credentials) {
    // 模拟登录
    userInfo.value = { name: credentials.username, token: 'abc123' };
  }
  function logout() {
    userInfo.value = { name: '', token: '' };
  }
  return { userInfo, isLoggedIn, login, logout };
});
7.2 互相调用与组合 Store
有时一个 Store 需要调用另一个 Store 的方法或读取状态,可以直接在内部通过 useXXXStore() 获取相应实例。例如在 cartStore.js 中,获取 userStore 中的登录信息来确定能否结账:
// src/stores/cartStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { useUserStore } from './userStore';
export const useCartStore = defineStore('cart', () => {
  const items = ref([]);
  const userStore = useUserStore();
  function addToCart(product) {
    items.value.push(product);
  }
  // 只有登录用户才能结账
  function checkout() {
    if (!userStore.isLoggedIn) {
      throw new Error('请先登录');
    }
    // 结账逻辑...
    items.value = [];
  }
  const totalPrice = computed(() => items.value.reduce((sum, p) => sum + p.price, 0));
  return { items, totalPrice, addToCart, checkout };
});
- 注意:在任意 Store 内以 function 调用 useUserStore(),Pinia 会确保返回相同实例。
插件与持久化策略
8.1 Pinia 插件机制简介
Pinia 支持插件,可以在创建 Store 时注入额外功能,例如:日志记录、状态持久化、订阅等。插件形式为一个接收上下文的函数,示例:
// src/plugins/logger.js
export function logger({ store }) {
  // 在每次 action 执行前后输出日志
  store.$onAction(({ name, args, after, onError }) => {
    console.log(`⏩ Action ${name} 开始,参数:`, args);
    after((result) => {
      console.log(`✅ Action ${name} 结束,返回:`, result);
    });
    onError((error) => {
      console.error(`❌ Action ${name} 报错:`, error);
    });
  });
}
在主入口注册插件:
// src/main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import { logger } from './plugins/logger';
const app = createApp(App);
const pinia = createPinia();
// 使用 logger 插件
pinia.use(logger);
app.use(pinia);
app.mount('#app');
- 这样所有 Store 在调用 Action 时,都会执行插件中的日志逻辑。
8.2 使用 pinia-plugin-persistedstate 实现持久化
依赖:pinia-plugin-persistedstate
npm install pinia-plugin-persistedstate
在入口文件中配置:
// src/main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import piniaPersist from 'pinia-plugin-persistedstate';
import App from './App.vue';
const app = createApp(App);
const pinia = createPinia();
// 注册持久化插件
pinia.use(piniaPersist);
app.use(pinia);
app.mount('#app');
在需要持久化的 Store 中添加 persist: true 配置:
// src/stores/userStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useUserStore = defineStore('user', {
  state: () => ({
    userInfo: { name: '', token: '' }
  }),
  getters: {
    isLoggedIn: (state) => !!state.userInfo.token
  },
  actions: {
    login(credentials) {
      this.userInfo = { name: credentials.username, token: 'abc123' };
    },
    logout() {
      this.userInfo = { name: '', token: '' };
    }
  },
  persist: {
    enabled: true,
    storage: localStorage, // 默认就是 localStorage
    paths: ['userInfo']     // 只持久化 userInfo 字段
  }
});
- 之后刷新页面 userInfo会从localStorage中恢复,无需再次登录。
8.3 自定义简单持久化方案示例
如果不想引入插件,也可以在 Store 内手动读写 LocalStorage:
// src/stores/cartStore.js
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useCartStore = defineStore('cart', () => {
  const items = ref(JSON.parse(localStorage.getItem('cartItems') || '[]'));
  function addToCart(product) {
    items.value.push(product);
    localStorage.setItem('cartItems', JSON.stringify(items.value));
  }
  function clearCart() {
    items.value = [];
    localStorage.removeItem('cartItems');
  }
  return { items, addToCart, clearCart };
});
- 在每次更新 items时,将新值写入 LocalStorage;组件挂载时从 LocalStorage 初始化状态。
Pinia Devtools 调试
9.1 安装与启用
- Chrome/Firefox 扩展:在浏览器扩展商店搜索 “Pinia Devtools” 并安装;
- 在代码中启用(Vue3 + Vite 默认自动启用 Devtools,不需额外配置);
启动应用后打开浏览器开发者工具,你会看到一个 “Pinia” 选项卡,列出所有 Store、state、getter、action 调用记录。
9.2 调试示意图
┌────────────────────────────────────────────────┐
│                Pinia Devtools                 │
│  ┌───────────┐   ┌─────────────┐  ┌───────────┐ │
│  │  Stores   │ → │  State Tree  │→│ Actions    │ │
│  └───────────┘   └─────────────┘  └───────────┘ │
│        ↓             ↓             ↓           │
│   点击查看       查看当前 state    查看执行     │
│               及 getters 更新     过的 actions  │
└────────────────────────────────────────────────┘
- Stores 面板:列出所有已注册的 Store 及其 id;
- State Tree 面板:查看某个 Store 的当前 state 和 getters;
- Actions 面板:记录每次调用 Action 的时间、传入参数与返回结果,方便回溯和调试;
实战示例:Todo List 应用
下面用一个 Todo List 应用将上述知识串联起来,完整演示 Pinia 在实际业务中的用法。
10.1 项目目录与功能描述
src/
├─ components/
│  ├─ TodoApp.vue
│  ├─ TodoInput.vue
│  └─ TodoList.vue
├─ stores/
│  └─ todoStore.js
└─ main.js
功能:
- 输入框添加待办
- 列表展示待办,可切换完成状态、删除
- 顶部显示未完成条目数
- 保存到 LocalStorage 持久化
10.2 编写 useTodoStore
// src/stores/todoStore.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useTodoStore = defineStore('todo', () => {
  // 1. 初始化 state,从本地存储恢复
  const todos = ref(
    JSON.parse(localStorage.getItem('todos') || '[]')
  );
  // 2. getters
  const incompleteCount = computed(() =>
    todos.value.filter((t) => !t.done).length
  );
  // 3. actions
  function addTodo(text) {
    todos.value.push({ id: Date.now(), text, done: false });
    persist();
  }
  function removeTodo(id) {
    todos.value = todos.value.filter((t) => t.id !== id);
    persist();
  }
  function toggleTodo(id) {
    const item = todos.value.find((t) => t.id === id);
    if (item) item.done = !item.done;
    persist();
  }
  function persist() {
    localStorage.setItem('todos', JSON.stringify(todos.value));
  }
  return { todos, incompleteCount, addTodo, removeTodo, toggleTodo };
});
- 每次增删改都调用 persist()将最新todos写入 LocalStorage,保证刷新不丢失。
10.3 组件实现:添加、删除、标记完成
10.3.1 TodoInput.vue
<template>
  <div class="todo-input">
    <input
      v-model="text"
      @keydown.enter.prevent="submit"
      placeholder="输入待办后按回车"
    />
    <button @click="submit">添加</button>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { useTodoStore } from '@/stores/todoStore';
const text = ref('');
const todoStore = useTodoStore();
function submit() {
  if (!text.value.trim()) return;
  todoStore.addTodo(text.value.trim());
  text.value = '';
}
</script>
<style scoped>
.todo-input {
  display: flex;
  margin-bottom: 16px;
}
.todo-input input {
  flex: 1;
  padding: 6px;
}
.todo-input button {
  margin-left: 8px;
  padding: 6px 12px;
}
</style>
- useTodoStore():拿到同一个 Store 实例,调用- addTodo将新待办加入。
10.3.2 TodoList.vue
<template>
  <ul class="todo-list">
    <li v-for="item in todos" :key="item.id" class="todo-item">
      <input
        type="checkbox"
        :checked="item.done"
        @change="toggle(item.id)"
      />
      <span :class="{ done: item.done }">{{ item.text }}</span>
      <button @click="remove(item.id)">删除</button>
    </li>
  </ul>
</template>
<script setup>
import { useTodoStore } from '@/stores/todoStore';
const todoStore = useTodoStore();
const { todos, toggleTodo, removeTodo } = todoStore;
// 包装一层方法,方便模板调用
function toggle(id) {
  toggleTodo(id);
}
function remove(id) {
  removeTodo(id);
}
</script>
<style scoped>
.todo-list {
  list-style: none;
  padding: 0;
}
.todo-item {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.done {
  text-decoration: line-through;
}
button {
  margin-left: auto;
  padding: 2px 8px;
}
</style>
- 直接引用 todoStore.todos渲染列表,toggleTodo与removeTodo修改状态并持久化。
10.3.3 TodoApp.vue
<template>
  <div class="todo-app">
    <h2>Vue3 + Pinia Todo 应用</h2>
    <TodoInput />
    <TodoList />
    <p>未完成:{{ incompleteCount }}</p>
  </div>
</template>
<script setup>
import TodoInput from '@/components/TodoInput.vue';
import TodoList from '@/components/TodoList.vue';
import { useTodoStore } from '@/stores/todoStore';
const todoStore = useTodoStore();
const { incompleteCount } = todoStore;
</script>
<style scoped>
.todo-app {
  max-width: 400px;
  margin: 20px auto;
  padding: 16px;
  border: 1px solid #ccc;
}
</style>
- 组件只需引入子组件,并从 Store 中读取 incompleteCount,实现整体展示。
10.4 整体数据流动图解
┌─────────────────────────────────────────────────────────┐
│                      TodoApp                           │
│  ┌──────────┐        ┌──────────┐        ┌────────────┐  │
│  │ TodoInput│        │ TodoList │        │ incomplete │  │
│  └──────────┘        └──────────┘        └────────────┘  │
│        ↓                     ↓                     ↑     │
│  user 输入 → addTodo() →    toggle/removeTodo()   │     │
│        ↓                     ↓                     │     │
│  todoStore.todos  ←─────────┘                     │     │
│        ↓                                           │     │
│  localStorage ← persist()                          │     │
└─────────────────────────────────────────────────────────┘
- 用户在 TodoInput里调用addTodo(text),Store 更新todos,子组件TodoList自动响应渲染新条目。
- 点击复选框或删除按钮调用 toggleTodo(id)或removeTodo(id), Store 更新并同步到 LocalStorage。
- incompleteCountgetter 根据- todos实时计算并展示。
高级用法:组合 Store 与插件扩展
11.1 组合式 Store:useCounter 调用 useTodo
有时想在一个 Store 内重用另一个 Store 的逻辑,可在 setup 中直接调用。示例:实现一个同时维护“计数”与“待办”的综合 Store:
// src/stores/appStore.js
import { defineStore } from 'pinia';
import { useCounterStore } from './counterStore';
import { useTodoStore } from './todoStore';
import { computed } from 'vue';
export const useAppStore = defineStore('app', () => {
  const counterStore = useCounterStore();
  const todoStore = useTodoStore();
  // 复用两个 Store 的状态与方法
  const totalItems = computed(() => todoStore.todos.length);
  function incrementAndAddTodo(text) {
    counterStore.increment();
    todoStore.addTodo(text);
  }
  return {
    count: counterStore.count,
    increment: counterStore.increment,
    todos: todoStore.todos,
    addTodo: todoStore.addTodo,
    totalItems,
    incrementAndAddTodo
  };
});
- useAppStore自动依赖- counterStore和- todoStore的状态与方法,方便在组件中一次性引入。
11.2 自定义插件示例:日志打印插件
前面在 8.1 中演示了一个简单的 logger 插件,下面给出更完整示例:
// src/plugins/logger.js
export function logger({ options, store }) {
  // store.$id 为当前 Store 的 id
  console.log(`🔰 插件初始化:Store ID = ${store.$id}`, options);
  // 监听 state 更改
  store.$subscribe((mutation, state) => {
    console.log(`📦 Store(${store.$id}) Mutation: `, mutation);
    console.log(`📦 New state: `, state);
  });
  // 监听 action 调用
  store.$onAction(({ name, args, after, onError }) => {
    console.log(`▶ Action(${store.$id}/${name}) 调用开始,参数:`, args);
    after((result) => {
      console.log(`✔ Action(${store.$id}/${name}) 调用结束,结果:`, result);
    });
    onError((error) => {
      console.error(`✖ Action(${store.$id}/${name}) 调用出错:`, error);
    });
  });
}
在 main.js 中注册:
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import { logger } from './plugins/logger';
const app = createApp(App);
const pinia = createPinia();
pinia.use(logger);
app.use(pinia);
app.mount('#app');
- 每当某个 Store 的 state 变更,或调用 Action,都在控制台打印日志,方便调试。
总结
本文从Pinia 简介、安装与配置、创建第一个 Store、组件内使用、Getters 与 Actions、模块化管理、插件与持久化、Devtools 调试,到实战 Todo List 应用、组合 Store、自定义插件等方面,对 Vue3 中 Pinia 的状态管理进行了全方位、实战详解。
- Pinia 上手极其简单:基于 Composition API,直接用 defineStore定义即可;
- 响应式与类型安全:无论是 JavaScript 还是 TypeScript 项目,都能享受自动推导和类型提示;
- 多 Store 划分与组合:可灵活拆分业务逻辑,又可在需要时将多个 Store 组合引用;
- 插件与持久化:Pinia 内置插件机制,让持久化、本地存储、日志、订阅等功能扩展便捷;
- Devtools 支持:通过浏览器插件即可可视化查看所有 Store、state、getters 和 action 日志。
掌握本文内容,相信你能轻松在 Vue3 项目中使用 Pinia 管理全局或跨组件状态,构建更清晰、更易维护的前端应用。