[toc]
| 单词 | 词性 | 音标 | 含义 |
|---|---|---|---|
| store | n. | /stɔː(r)/ | 仓库,Pinia 里集中存放共享数据的容器 |
| state | n. | /steɪt/ | 状态,store 里的共享数据(类似全局变量) |
| getter | n. | /ˈɡetə(r)/ | 派生值,由 state 算出来(类似 computed) |
| action | n. | /ˈækʃn/ | 动作,修改 state 的方法(类似函数) |
| shared | adj. | /ʃeə(r)d/ | 共享的,只有多个组件都要用、还会变的数据才进 store |
| defineStore | - | /dɪˈfaɪn stɔː(r)/ | 方法,用 defineStore 定义一个全局数据仓库 |
Lecture10-Pinia 状态管理
1、本节讲什么
学会把"多个组件都要用的数据"集中管理,类似后端的全局共享上下文。适合:登录用户、购物车、主题等。
2、概念速览
什么是状态:应用里"多个组件共享的数据"(如登录用户、购物车)。状态管理 = 把共享数据放一个中央仓库,任何组件都能读写。
正确 vs 误区:不是所有数据都要进 Pinia——只有"多个地方都要用、还会变"的数据才需要;组件自己的临时数据放组件里就行。
3、先看效果
任意组件都能读、能改同一个"计数器",且所有用到它的组件自动同步。
① 安装
npm install pinia
② main.ts 启用
import { createPinia } from 'pinia'
createApp(App).use(createPinia()).use(router).mount('#app')
③ src/stores/counter.ts(定义 store)
import { defineStore } from 'pinia'
// useCounterStore:一个全局数据仓库。所有组件共用这一份数据
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }), // 数据(类似全局变量)
getters: { double: (s) => s.count * 2 }, // 派生(类似 computed)
actions: {
increment() { this.count++ }, // 改数据的方法(类似函数)
},
})
④ 任意组件使用
<script setup lang="ts">
import { useCounterStore } from '../stores/counter'
const store = useCounterStore()
</script>
<template>
<p>count: {{ store.count }} · double: {{ store.double }}</p>
<button @click="store.increment()">+1</button>
</template>
4、照着做
- 安装并启用 Pinia。
- 建
src/stores/counter.ts。 - 在两个不同组件里都用这个 store,点一个 +1,看另一个是否同步。
对比 props:为什么 props 不能被 Pinia 取代
| 场景 | 用什么 | 为什么 |
|---|---|---|
| 父组件给子组件一次性传参(如列表→行、配置→组件) | props / 事件 | 这是组件的"接口",让组件可复用、可参数化 |
| 多个不相干组件共享一份会变的全局数据 | Pinia | 需要"中央仓库"统一管理 |
| 跨多层(爷爷→孙子的孙子) | provide/inject | 省得一层层传,但用得少 |
一句话:props 是"组件之间的参数传递"(局部、一次性),Pinia 是"全局共享仓库"(全局、多组件)——它俩解决的不是同一类问题。
为什么不建议全都用 Pinia:把每个父子传参都塞进全局 store,store 会越来越臃肿、组件失去独立性、数据流向不清——这恰恰是"屎山"的来源。正确做法是:能局部(props)就局部,只有真正全局共享才用 Pinia。
5、常见疑问
- Q:什么时候该用 Pinia,什么时候不该? A:只有"多个组件真需要共享"的数据才放 store(如登录状态、购物车)。单组件自己的数据就放组件里,别全塞 store,否则一团乱。
- Q:
state / getters / actions各是什么? A:state=共享数据;getters=由 state 算出来的派生数据;actions=修改数据的方法。和组件里的 ref/computed/函数一一对应。 - Q:组件能直接改 store 的 state 吗?
A:能(
store.count++),但更推荐通过actions改,方便统一处理逻辑(比如改之前先校验)。
6、规范要点
- store 按业务域拆(
user.ts、cart.ts),别一个 store 塞所有东西。 - 修改状态走 actions,别在组件里到处
store.xxx++。 - 命名:store 文件名小写驼峰,导出
useXxxStore。
7、本节验证
- 会安装并启用 Pinia(
createPinia()+.use())✅ - 会用
defineStore定义 state / getters / actions ✅ - 会在任意组件里
useXxxStore()读写同一份共享数据 ✅ - 说得清 props 与 Pinia 各自的适用场景,不乱塞全局 store ✅