第八章:Pinia — 状态管理
上一章解决了”页面切换”,这一章解决”数据共享”:当很多组件都要用同一份数据时,怎么办?
8.1 一个痛点:数据在组件间传得太累
回忆入门篇:父组件通过 props 把数据传给子组件。这在简单场景没问题,但项目一大就崩了。
设想一个场景:用户登录信息(用户名、头像),需要在这些地方用到:
- 顶部导航栏(显示头像)
- 个人中心页(显示用户名)
- 聊天页(发消息时带上用户名)
- ……
如果靠 props 一层层传,会变成这样的噩梦:
App
└─ 传给 → 布局组件
└─ 传给 → 导航栏
└─ 传给 → 用户菜单
└─ 终于用上了头像
明明只是导航栏最里层要用一下头像,却要中间每一层都”帮忙传递”一遍。这叫 “props 逐层透传”,又累又难维护。
Pinia 就是来终结这种痛苦的。
8.2 Pinia 是什么
一句话:
Pinia 是一个”全局数据仓库”,任何组件都能直接从里面取数据、改数据,不用再一层层传。
把它想象成项目里的一个公共储物柜:
- 登录后,把用户信息存进储物柜
- 导航栏要头像?直接去储物柜拿
- 聊天页要用户名?也直接去拿
谁都能直接访问,不用互相传递。这就是”状态管理”(“状态”就是”数据”的另一种说法)。
Pinia 是 Vue 官方推荐的状态管理库,取代了老的 Vuex,更简单。
8.3 核心三件套
一个 Pinia 仓库(叫 store)由三部分组成,其实和 Vue 组件的思路很像:
| 名称 | 作用 | 类比 |
|---|---|---|
state | 存放数据 | 组件里的 ref 数据 |
getters | 基于数据的计算 | 组件里的计算属性 |
actions | 修改数据的方法 | 组件里的函数 |
8.4 一个最小示例
第一步:安装并启用
npm install pinia
在 main.js 里启用:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
createApp(App).use(createPinia()).mount('#app')
第二步:定义一个 store
新建 src/stores/user.js:
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
// state:存数据
state: () => ({
name: '游客',
isLogin: false
}),
// getters:基于数据的计算
getters: {
welcomeText: (state) => `你好,${state.name}`
},
// actions:修改数据的方法
actions: {
login(name) {
this.name = name
this.isLogin = true
},
logout() {
this.name = '游客'
this.isLogin = false
}
}
})
第三步:在任意组件里使用
A 组件(比如登录页)里改数据:
<script setup>
import { useUserStore } from '../stores/user'
const userStore = useUserStore()
function handleLogin() {
userStore.login('小明') // 调用 action 修改仓库数据
}
</script>
<template>
<button @click="handleLogin">登录</button>
</template>
B 组件(比如导航栏)里读同一份数据,完全不需要 A 传给它:
<script setup>
import { useUserStore } from '../stores/user'
const userStore = useUserStore()
</script>
<template>
<div>{{ userStore.welcomeText }}</div>
<!-- A 组件点了登录后,这里会自动变成 "你好,小明" -->
</template>
关键点:A 组件登录改了仓库里的 name,B 组件显示的内容会自动更新——因为它们读的是同一个仓库。数据驱动的威力,跨组件也成立。
8.5 什么时候才需要它
⚠️ 重要提醒:不要为了用而用。
- 小项目 / 简单页面:父子传 props 就够了,别急着上 Pinia
- 需要跨很多组件共享数据时(登录信息、购物车、全局主题设置……):才用 Pinia
判断标准:当你发现”某个数据要靠 props 传好几层”,或者”好几个不相干的组件都要用同一份数据”,就是该上 Pinia 的信号。
8.6 小结
- 痛点:数据靠 props 逐层透传,组件一多就成噩梦
- Pinia = 全局数据仓库(公共储物柜),任何组件直接存取,无需层层传递
- 核心三件套:
state(存数据)getters(算数据,类似计算属性)actions(改数据的方法)
- 用法:
npm install pinia→main.js启用 →defineStore定义 → 组件里useXxxStore()用 - 一处修改,所有用到的组件自动更新
- 够用就好:小项目别硬上,跨组件共享多了再用
下一章:页面有了、数据能共享了,但数据得从后端拿回来才行 —— 网络请求神器 Axios。