Vue3中Pinia状态管理实战详解‌

目录

  1. 前言
  2. Pinia 简介
  3. 环境准备与安装

    • 3.1 Vue3 项目初始化
    • 3.2 安装 Pinia
  4. 创建第一个 Store

    • 4.1 定义 Store 文件结构
    • 4.2 defineStore 详解
    • 4.3 ASCII 图解:响应式状态流动
  5. 在组件中使用 Pinia

    • 5.1 根应用挂载 Pinia
    • 5.2 组件内调用 Store
    • 5.3 响应式更新示例
  6. Getters 与 Actions 深度解析

    • 6.1 Getters(计算属性)的使用场景
    • 6.2 Actions(方法)的使用场景
    • 6.3 异步 Action 与 API 请求
  7. 模块化与多 Store 管理

    • 7.1 多个 Store 的组织方式
    • 7.2 互相调用与组合 Store
  8. 插件与持久化策略

    • 8.1 Pinia 插件机制简介
    • 8.2 使用 pinia-plugin-persistedstate 实现持久化
    • 8.3 自定义简单持久化方案示例
  9. Pinia Devtools 调试

    • 9.1 安装与启用
    • 9.2 调试示意图
  10. 实战示例:Todo List 应用

    • 10.1 项目目录与功能描述
    • 10.2 编写 useTodoStore
    • 10.3 组件实现:添加、删除、标记完成
    • 10.4 整体数据流动图解
  11. 高级用法:组合 Store 与插件扩展

    • 11.1 组合式 Store:useCounter 调用 useTodo
    • 11.2 自定义插件示例:日志打印插件
  12. 总结

前言

在 Vue3 中,Pinia 已经正式取代了 Vuex,成为官方推荐的状态管理工具。Pinia 以“轻量、直观、类型安全”为目标,通过 Composition API 的方式定义和使用 Store,不仅上手更快,还能借助 TypeScript 获得良好体验。本文将从安装与配置入手,结合代码示例图解,深入讲解 Pinia 各项核心功能,帮助你在实际项目中快速掌握状态管理全流程。


Pinia 简介

  • 什么是 Pinia:Pinia 是 Vue3 的状态管理库,类似于 Vuex,但接口更简洁,使用 Composition API 定义 Store,无需繁重的模块结构。
  • 核心特点

    1. 基于 Composition API:使用 defineStore 定义,返回函数式 API,易于逻辑复用;
    2. 响应式状态:Store 内部状态用 ref/reactive 管理,组件通过直接引用或解构获取响应式值;
    3. 轻量快速:打包后体积小,无复杂插件系统;
    4. 类型安全:与 TypeScript 一起使用时,可自动推导 state、getters、actions 的类型;
    5. 插件机制:支持持久化、订阅、日志等插件扩展。

环境准备与安装

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 下新建 storesstore 目录,用于集中存放所有 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 更新。
  • 方法 incrementincrementBy:对状态进行更改。

4.3 ASCII 图解:响应式状态流动

┌───────────────────────────┐
│     useCounterStore()     │
│ ┌────────┐  ┌───────────┐ │
│ │ count  │→ │ increment │ │
│ │  ref   │  └───────────┘ │
│ └────────┘   ┌──────────┐ │
│               │ double  │ │
│               │ Count   │ │
│               └──────────┘ │
└───────────────────────────┘

组件 ←─── 读取 count / doubleCount ───→ 自动更新
组件 ── 调用 increment() ──▶ count.value++
  • 组件挂载时,调用 useCounterStore() 拿到同一个 Store 实例,读取 countdoubleCount 时会自动收集依赖;
  • 当调用 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>
  • 组件渲染时countdoubleCount 自动读取 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 };
});
  • 异步 Action 示例:从服务器拉取初始列表
// 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 调用异步 Action fetchTodos(),并通过解构获取 loadingerrortodosincompleteCount
  • 按钮点击调用同步 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  │
└────────────────────────────────────────────────┘
  1. Stores 面板:列出所有已注册的 Store 及其 id;
  2. State Tree 面板:查看某个 Store 的当前 state 和 getters;
  3. 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 渲染列表,toggleTodoremoveTodo 修改状态并持久化。

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。
  • incompleteCount getter 根据 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 自动依赖 counterStoretodoStore 的状态与方法,方便在组件中一次性引入。

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 管理全局或跨组件状态,构建更清晰、更易维护的前端应用。

VUE
最后修改于:2025年06月01日 22:57

评论已关闭

推荐阅读

DDPG 模型解析,附Pytorch完整代码
2024年11月24日
DQN 模型解析,附Pytorch完整代码
2024年11月24日
AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日