📚 Pinia 状态管理集成教程(Vue 3 项目实战)
本教程将手把手教你为 Vue 3 项目集成 Pinia,实现全局状态管理,适用于个人信息、地址管理等模块。
🎯 学习目标
- 安装并配置 Pinia
- 创建 Store 管理用户数据
- 在组件中使用 Store
- 实现编辑/保存的隔离状态
⚙️ 第 1 步:安装 Pinia
npm install pinia
💡 验证安装:
package.json中应出现"pinia": "^2.x.x"
🏗️ 第 2 步:创建 Store
1. 创建目录结构
src/
└── stores/
└── user.js # 用户数据 Store
2. 编写 src/stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
// 状态(相当于 Vuex 的 state)
state: () => ({
// 用户信息
userData: {
nickname: 'Vue Learner',
telno: '138****1234'
},
isEditing: false, // 个人信息编辑状态
// 地址列表
addresses: [
{ id: 1, name: '张三', phone: '138****1234', address: '北京市朝阳区' }
],
editingAddress: null // null=新增地址, {id,...}=编辑地址
}),
// 方法(相当于 Vuex 的 mutations + actions)
actions: {
// 更新用户字段
updateField(field, value) {
this.userData[field] = value
},
// 切换个人信息编辑状态
setEditing(editing) {
this.isEditing = editing
},
// 地址管理
addAddress(data) {
this.addresses.push({ ...data, id: Date.now() })
},
updateAddress(id, data) {
const addr = this.addresses.find(a => a.id === id)
if (addr) Object.assign(addr, data)
},
deleteAddress(id) {
this.addresses = this.addresses.filter(a => a.id !== id)
},
setEditingAddress(addr) {
this.editingAddress = addr
}
}
})
🔑 关键点:
state必须是函数(返回初始状态对象)actions可直接修改this(无需 return 新状态)
🔌 第 3 步:在项目中注册 Pinia
修改 src/main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia' // 1. 引入 createPinia
import App from './App.vue'
import './assets/main.css'
const app = createApp(App)
const pinia = createPinia() // 2. 创建 Pinia 实例
app.use(pinia) // 3. 注册 Pinia
app.mount('#app')
⚠️ 必须先
app.use(pinia)再app.mount(),否则组件中调用useStore()会报错!
🧩 第 4 步:在组件中使用 Store
1. 导入 Store
<script setup>
import { useUserStore } from '@/stores/user'
const userStore = useUserStore() // 获取 store 实例
</script>
2. 读取状态
<template>
<!-- 直接访问 store 数据 -->
<p>昵称:{{ userStore.userData.nickname }}</p>
</template>
3. 调用方法
// 更新数据
userStore.updateField('nickname', '新昵称')
// 切换状态
userStore.setEditing(true)
🛡️ 第 5 步:实现编辑隔离(关键技巧)
问题场景
编辑表单时,不能直接修改 store 数据(否则取消编辑会保留错误输入)
解决方案:本地草稿区 + 保存时提交
<script setup>
import { ref } from 'vue'
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
// 1. 从 store 复制初始值(创建草稿)
const nickname = ref(userStore.userData.nickname)
const telno = ref(userStore.userData.telno)
// 2. 保存时提交到 store
const onSave = () => {
// 验证通过后更新 store
userStore.updateField('nickname', nickname.value)
userStore.updateField('telno', telno.value)
userStore.setEditing(false) // 关闭编辑
}
// 3. 取消时丢弃草稿
const onCancel = () => {
userStore.setEditing(false)
}
</script>
<template>
<!-- 绑定本地 ref(非 store) -->
<input v-model="nickname" />
<input v-model="telno" />
<button @click="onSave">保存</button>
<button @click="onCancel">取消</button>
</template>
✅ 优势:
- 编辑过程不污染全局状态
- 取消操作零成本(直接丢弃本地变量)
🧪 验证清单
- 安装 Pinia 无报错
-
main.js中先use(pinia)后mount() - 组件中能读取
userStore.userData - 编辑表单使用本地
ref作为草稿区 - 保存时才更新 store,取消时不更新
💡 最佳实践
| 场景 | 推荐做法 |
|---|---|
| 简单状态 | 直接读写 userStore.xxx |
| 表单编辑 | 用 ref/reactive 作草稿区 |
| 复杂逻辑 | 在 actions 中封装业务逻辑 |
| 多模块 | 拆分为 userStore/cartStore 等 |
🚀 下一步
完成本教程后,你的项目将具备:
- 全局状态管理能力
- 安全的表单编辑流程
- 可扩展的 Store 结构
需要 地址管理模块的 Pinia 实现细节 或 数据持久化方案 吗? 😊