目录
1. 什么是 Pinia?
Pinia 就像一个全局的数据仓库,让不同的 Vue 组件能够共享数据。
比喻:想象一个图书馆(Pinia),所有人(Vue组件)都可以去借书(读取数据)、还书(修改数据)。
2. 为什么需要 Pinia?
问题场景:
// 组件A需要用户信息
const userInfo = { name: '张三', age: 25 }
// 组件B也需要这个用户信息
// 组件C也需要这个用户信息
// 怎么在这些组件之间共享数据?
解决方案:用 Pinia 存储全局数据,所有组件都能访问。
3. Pinia 的三个核心概念
State(状态)- 存储数据
state: () => ({
currentType: 'type1', // 当前机器类型
userInfo: null, // 用户信息
count: 0 // 计数器
})
理解:State 就是存放数据的地方,类似于组件的 data。
Getters(计算属性)- 处理数据
getters: {
// 根据当前类型获取配置
currentConfig: (state) => {
return state.machineConfig[state.currentType]
},
// 判断是否是成年人
isAdult: (state) => {
return state.userInfo?.age >= 18
}
}
理解:Getters 就像计算属性,基于 state 计算出新的值。
Actions(方法)- 修改数据
actions: {
// 设置机器类型
setMachineType(type) {
this.currentType = type
},
// 设置用户信息
setUserInfo(info) {
this.userInfo = info
}
}
理解:Actions 就是修改 state 的方法,类似于组件的 methods。
4. 创建一个简单的 Store
让我们创建一个用户信息的 Store:
// store/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
// 1. State - 存储数据
state: () => ({
name: '',
age: 0,
isLogin: false
}),
// 2. Getters - 计算属性
getters: {
// 获取用户显示名称
displayName: (state) => {
return state.name || '游客'
},
// 判断是否成年
isAdult: (state) => {
return state.age >= 18
}
},
// 3. Actions - 修改数据的方法
actions: {
// 登录
login(name, age) {
this.name = name
this.age = age
this.isLogin = true
},
// 登出
logout() {
this.name = ''
this.age = 0
this.isLogin = false
}
}
})
5. 在组件中使用 Store
<!-- UserProfile.vue -->
<template>
<div>
<h1>用户信息</h1>
<p>姓名:{{ userStore.displayName }}</p>
<p>年龄:{{ userStore.age }}</p>
<p>状态:{{ userStore.isLogin ? '已登录' : '未登录' }}</p>
<p>{{ userStore.isAdult ? '成年人' : '未成年人' }}</p>
<button @click="handleLogin">登录</button>
<button @click="handleLogout">登出</button>
</div>
</template>
<script setup>
import { useUserStore } from '@/store/user'
// 获取 store 实例
const userStore = useUserStore()
// 登录方法
const handleLogin = () => {
userStore.login('张三', 25)
}
// 登出方法
const handleLogout = () => {
userStore.logout()
}
</script>
6. 再来一个示例
创建一个机型配置 Store:
export const useMachineStore = defineStore('machine', {
// 存储机器相关数据
state: () => ({
currentType: 'type1', // 当前机器类型
machineConfig: { // 机器配置信息
type1: { name: '无打印', features: ['query', 'payment'] },
type2: { name: '报告打印', features: ['query', 'payment', 'reportPrint'] },
type3: { name: '发票打印', features: ['query', 'payment', 'invoicePrint'] }
}
}),
// 基于数据计算新值
getters: {
// 获取当前机器配置
currentConfig: (state) => {
return state.machineConfig[state.currentType]
},
// 检查是否支持某功能
hasFeature: (state) => {
return (feature) => {
const config = state.machineConfig[state.currentType]
return config.features.includes(feature)
}
}
},
// 修改数据的方法
actions: {
// 切换机器类型
setMachineType(type) {
this.currentType = type
}
}
})
7. 在组件中的使用示例
<!-- MachineInfo.vue -->
<template>
<div>
<h2>{{ machineStore.currentConfig.name }}</h2>
<p>支持的功能:</p>
<ul>
<li v-if="machineStore.hasFeature('query')">查询功能</li>
<li v-if="machineStore.hasFeature('payment')">缴费功能</li>
<li v-if="machineStore.hasFeature('reportPrint')">报告打印</li>
</ul>
<button @click="switchMachine">切换机器类型</button>
</div>
</template>
<script setup>
import { useMachineStore } from '@/store/machine'
const machineStore = useMachineStore()
const switchMachine = () => {
// 切换到下一个类型
const types = ['type1', 'type2', 'type3']
const currentIndex = types.indexOf(machineStore.currentType)
const nextIndex = (currentIndex + 1) % types.length
machineStore.setMachineType(types[nextIndex])
}
</script>
8. Pinia 的优势
- 简单易用:语法简洁,容易理解。
- 类型安全:支持 TypeScript。
- 开发工具:有专门的调试工具。
- 模块化:每个功能可以创建独立的 store。
9. 常见使用场景
- 用户信息管理:登录状态、用户资料。
- 主题设置:暗色模式、语言设置。
- 购物车:商品列表、总价计算。
- 全局配置:API 地址、系统设置。
10. 学习建议
- 从简单开始:先创建一个计数器 store。
- 理解概念:state存数据,getters算数据,actions改数据。
- 多练习:在实际项目中使用。
- 看文档:官方文档很详细。