Pinia

Pinia 简介与安装

了解 Pinia 是什么、为什么要用它替代 Vuex,以及如何在 Vue3 项目中安装和初始化 Pinia。

🎯 引言

学会这篇文章,你能明白 Pinia 是什么、它解决了什么问题,以及为什么 Vue3 官方更推荐用它管理状态。你还会完成 Pinia 的安装和初始化,写出一个最简单的计数器 Store。


🧱 什么是 Pinia

Pinia 是 Vue 官方推荐的状态管理库,专门面向 Vue3 设计,也兼容 Vue2。

它的作用很简单:把多个组件都需要的数据放到一个公共的地方集中管理。这样任意组件都能读取或修改同一份数据,不用再一层层传 props、一层层发事件。

举个例子:

  • 组件 A 修改了用户头像。
  • 组件 B 和组件 C 都要显示这个头像。

如果没有状态管理,A 需要通知父组件,父组件再传给 B 和 C。有了 Pinia,三个组件直接读写同一个 userStore,代码会清爽很多。


✨ 为什么 Vue3 更推荐 Pinia

Pinia 不是凭空出现的,它是为了解决 Vuex 在 Vue3 项目中的几个痛点:

痛点VuexPinia
修改状态必须先写 mutation,再提交可以直接修改,也可以写到 action 里
TypeScript类型支持比较弱原生支持,类型推断自然
模块拆分需要配置 namespace每个 Store 天然独立
学习成本概念多(state/mutation/action/module)概念少(state/getter/action)
Pinia 不是把 Vuex 变复杂,而是把它变简单了。如果你之前学过 Vuex,学 Pinia 会非常快。

🚀 安装 Pinia

在 Vite 或 Vue CLI 创建的 Vue3 项目中,安装只需要一行命令:

npm install pinia

安装完成后,在 main.js 中注册:

main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';

const app = createApp(App);

app.use(createPinia());
app.mount('#app');
createPinia() 必须在 app.mount() 之前调用,否则组件里会找不到 Pinia 实例。

🛠 第一个计数器 Store

注册完成后,就可以创建 Store 了。下面是一个最简单的例子,后续文章会逐步拆解每一部分。

stores/counter.js
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
    state: () => ({
        count: 0,
    }),
    getters: {
        double() {
            return this.count * 2;
        },
    },
    actions: {
        add() {
            this.count++;
        },
    },
});

在组件中使用:

App.vue
<template>
    <p>计数:{{ counter.count }}</p>
    <p>双倍:{{ counter.double }}</p>
    <button @click="counter.add">加一</button>
</template>

<script setup>
import { useCounterStore } from './stores/counter.js';

const counter = useCounterStore();
</script>
useCounterStore 是我们约定的命名,所有 Pinia Store 都建议以 use 开头、以 Store 结尾,方便一眼认出它是状态管理。

🧾 小节总结

  • Pinia 是 Vue 官方推荐的状态管理库,用来集中管理多个组件共享的数据。
  • 相比 Vuex,Pinia 概念更少、TypeScript 支持更好、Store 天然独立。
  • 使用 npm install pinia 安装,并在 main.js 中用 app.use(createPinia()) 注册。
  • Store 通过 defineStore() 定义,第一参数是全局唯一 ID,第二参数是配置对象。

❓ 知识问答

Q1:Pinia 只能在 Vue3 里用吗?

也能在 Vue2 里用,但在 Vue3 中体验最好,是官方首选。

Q2:Pinia 和 Vuex 是什么关系?

都是 Vue 生态的状态管理方案。Pinia 可以看作 Vuex 的继任者,官方文档已经把 Pinia 列为 Vue3 的默认推荐。

Q3:defineStore 第一个参数为什么不能用重复的名字?

它是 Store 的全局 ID,Pinia 靠这个 ID 区分不同的 Store。重复会导致状态混乱。

Q4:Store 文件一定要放在 stores 目录吗?

不是强制的,但这是社区约定,方便维护。放在哪里只要引入路径正确都可以。


🧪 小练习

按照下面的步骤,创建一个 useScoreStore

  1. stores/score.js 中定义 Store,ID 为 'score'
  2. state 中有一个 score,初始值为 0
  3. actions 中有一个 add(),让 score10
  4. 在组件中显示 score,点击按钮调用 add()
stores/score.js
import { defineStore } from 'pinia';

// 请在这里编写代码
App.vue
<template>
    <p>分数:{{ score.score }}</p>
    <button @click="score.add">加分</button>
</template>

<script setup>
// 请在这里引入并创建 Store 实例
</script>

🎉 恭喜你完成了 Pinia 的入门!下一篇我们会详细拆解 Store 里的 stategettersactions 到底是什么、怎么用。