2.1 安装流程全解析
# 使用 npm 安装(推荐用于标准项目)
npm install pinia --save
# 使用 yarn 安装(推荐用于 Monorepo 项目)
yarn add pinia
# 针对 Vite 项目的优化安装(自动处理 Tree-shaking)
npm install pinia@next -D
安装注意事项:
- 需要 Vue3 运行时环境(要求 Vue >= 3.2)
- 与 Vue Router 无版本冲突
- 生产环境会自动启用 Tree-shaking
2.2 基础配置详解
// main.js(核心配置文件)
import { createApp } from 'vue'
import { createPinia } from 'pinia' // 导入 Pinia 工厂函数
import App from './App.vue'
/**
* 创建 Pinia 实例(重要!必须先于 Vue 实例创建)
* 功能:
* 1. 管理所有 Store 的注册表
* 2. 维护插件系统
* 3. 提供 devtools 集成
*/
const pinia = createPinia()
// 创建 Vue 应用实例
const app = createApp(App)
/**
* 安装 Pinia 插件(关键步骤!)
* 作用:
* 1. 注入 $pinia 到所有组件上下文
* 2. 启用开发工具支持
* 3. 激活响应式系统集成
*/
app.use(pinia)
// 挂载到 DOM
app.mount('#app')
配置要点说明:
- 必须确保
createPinia()
在根组件挂载前调用 app.use(pinia)
会在所有组件中注入useStore()
方法- 可在此处添加全局插件(后文会详细讲解)
2.3 创建第一个 Store 的两种方式
方式一:选项式 Store(推荐新手使用)
// stores/counter.js
import { defineStore } from 'pinia'
/**
* defineStore 参数说明:
* @param {string} 'counter' → Store 唯一ID(必须全局唯一)
* @param {object} 配置对象 → 包含 state/getters/actions
*/
export const useCounterStore = defineStore('counter', {
/**
* state 定义规范:
* 1. 必须使用工厂函数返回初始状态
* 2. 支持嵌套对象结构
* 3. 类型推导会自动工作
*/
state: () => ({
count: 0,
history: [] // 记录操作历史
}),
/**
* Getters 定义规则:
* 1. 接收 state 作为第一个参数
* 2. 可通过 this 访问整个 store 实例
* 3. 支持返回函数实现带参数的计算属性
*/
getters: {
doubleCount: (state) => state.count * 2,
formattedHistory: (state) => (separator = ', ') => state.history.join(separator)
},
/**
* Actions 定义要点:
* 1. 可以是同步或异步函数
* 2. 通过 this 直接访问和修改 state
* 3. 支持调用其他 actions
*/
actions: {
increment() {
// 直接修改状态
this.count++
// 调用其他 action
this.recordAction('increment')
},
async asyncIncrement() {
await new Promise(resolve => setTimeout(resolve, 1000))
this.increment()
},
recordAction(actionName) {
this.history.push({
action: actionName,
timestamp: new Date().toISOString()
})
}
}
})
方式二:组合式 Store(推荐 TypeScript 项目)
// stores/user.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useUserStore = defineStore('user', () => {
// State 定义(使用 ref/reactive)
const username = ref('')
const age = ref(0)
const loginHistory = ref<Date[]>([])
// Getters(使用 computed)
const isAdult = computed(() => age.value >= 18)
const lastLogin = computed(() => {
return loginHistory.value.length > 0
? loginHistory.value.slice(-1)[0]
: null
})
// Actions(普通函数)
function login() {
loginHistory.value.push(new Date())
localStorage.setItem('userToken', 'demo_token')
}
async function fetchProfile() {
const res = await fetch('/api/profile')
const data = await res.json()
username.value = data.name
age.value = data.age
}
return {
username,
age,
loginHistory,
isAdult,
lastLogin,
login,
fetchProfile
}
})
两种方式的对比说明:
特性 | 选项式 Store | 组合式 Store |
---|---|---|
适用场景 | 简单状态逻辑 | 复杂业务逻辑 |
TypeScript 支持 | 自动类型推断 | 更精确的类型控制 |
代码组织 | 按功能分类(state/getters/actions) | 按逻辑相关性组织 |
响应式系统 | 自动处理 | 需要显式使用 ref/computed |
可复用性 | 较低 | 更高(可提取逻辑函数) |
2.4 配置进阶技巧
多环境配置示例:
// 开发环境配置
const pinia = createPinia()
if (import.meta.env.MODE === 'development') {
pinia.use(devToolsPlugin) // 添加开发工具插件
pinia.use(loggerPlugin) // 添加状态变更日志
}
// 生产环境配置
if (import.meta.env.PROD) {
pinia.use(performancePlugin) // 添加性能监控
}
SSR 配置示例:
// server.js(服务端)
import { createPinia } from 'pinia'
export default function createSSRApp() {
const app = createApp(App)
const pinia = createPinia()
// 为每个请求创建新实例
app.use(pinia)
return { app, pinia }
}
// client.js(客户端)
const pinia = createPinia()
pinia.state.value = window.__PINIA_STATE__ // 同步服务端状态
2.5 常见问题排查
问题1:Store 未正确注册
// 错误现象:Cannot access 'useXxxStore' before initialization
// 解决方案:确保在组件中使用前完成注册
// ✅ 正确使用顺序:
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
问题2:响应性丢失
// 错误写法:
const { count } = useCounterStore() // 失去响应性!
// ✅ 正确做法:
const counter = useCounterStore()
// 在模板中直接使用 counter.count
// 或使用 storeToRefs:
import { storeToRefs } from 'pinia'
const { count } = storeToRefs(counter)
问题3:循环依赖
// stores/a.js 和 stores/b.js 互相引用
// ✅ 解决方案:
// 在 action 中动态导入
actions: {
async fetchData() {
const { useBStore } = await import('./b.js')
const bStore = useBStore()
// ...
}
}
本章核心要点:
- 安装顺序必须确保 Pinia 在 Vue 实例挂载前注册
- Store 定义可根据项目复杂度选择选项式或组合式
- SSR 配置需要特殊处理状态同步
- 响应性维护需注意解构操作的影响
- 环境区分可针对不同环境添加插件
通过本章的学习,应该能够正确完成 Pinia 的环境搭建,并理解不同 Store 定义方式的适用场景。接下来第三章将深入讲解核心概念的具体使用方法。