Pinia 简介与安装
🎯 引言
学会这篇文章,你能明白 Pinia 是什么、它解决了什么问题,以及为什么 Vue3 官方更推荐用它管理状态。你还会完成 Pinia 的安装和初始化,写出一个最简单的计数器 Store。
🧱 什么是 Pinia
Pinia 是 Vue 官方推荐的状态管理库,专门面向 Vue3 设计,也兼容 Vue2。
它的作用很简单:把多个组件都需要的数据放到一个公共的地方集中管理。这样任意组件都能读取或修改同一份数据,不用再一层层传 props、一层层发事件。
举个例子:
- 组件 A 修改了用户头像。
- 组件 B 和组件 C 都要显示这个头像。
如果没有状态管理,A 需要通知父组件,父组件再传给 B 和 C。有了 Pinia,三个组件直接读写同一个 userStore,代码会清爽很多。
✨ 为什么 Vue3 更推荐 Pinia
Pinia 不是凭空出现的,它是为了解决 Vuex 在 Vue3 项目中的几个痛点:
| 痛点 | Vuex | Pinia |
|---|---|---|
| 修改状态 | 必须先写 mutation,再提交 | 可以直接修改,也可以写到 action 里 |
| TypeScript | 类型支持比较弱 | 原生支持,类型推断自然 |
| 模块拆分 | 需要配置 namespace | 每个 Store 天然独立 |
| 学习成本 | 概念多(state/mutation/action/module) | 概念少(state/getter/action) |
🚀 安装 Pinia
在 Vite 或 Vue CLI 创建的 Vue3 项目中,安装只需要一行命令:
npm install pinia
安装完成后,在 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 了。下面是一个最简单的例子,后续文章会逐步拆解每一部分。
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
double() {
return this.count * 2;
},
},
actions: {
add() {
this.count++;
},
},
});
在组件中使用:
<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:
- 在
stores/score.js中定义 Store,ID 为'score'。 state中有一个score,初始值为0。actions中有一个add(),让score加10。- 在组件中显示
score,点击按钮调用add()。
import { defineStore } from 'pinia';
// 请在这里编写代码
<template>
<p>分数:{{ score.score }}</p>
<button @click="score.add">加分</button>
</template>
<script setup>
// 请在这里引入并创建 Store 实例
</script>
🎉 恭喜你完成了 Pinia 的入门!下一篇我们会详细拆解 Store 里的 state、getters、actions 到底是什么、怎么用。
