Vue3 Pina 使用指南
Pina 使用指南
Pina 是一个状态管理库,专为 Vue.js 应用程序设计。以下是 Pina 的主要使用方法和特性:
安装
npm install pinia
# 或
yarn add pinia
基本使用
1. 创建 Store
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
2. 在 Vue 应用中使用
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
3. 在组件中使用 Store
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
<template>
<div>Count: {{ counter.count }}</div>
<div>Double: {{ counter.doubleCount }}</div>
<button @click="counter.increment()">Increment</button>
</template>
核心概念
State
- 存储应用程序的状态
- 使用
store.$patch可以批量更新状态
counter.$patch({
count: counter.count + 1,
name: 'new name'
})
Getters
- 类似于计算属性
- 可以接收参数
getters: {
tripleCount: (state) => {
return (multiplier) => state.count * multiplier
}
}
Actions
- 相当于组件中的 methods
- 可以是异步的
actions: {
async fetchUser() {
this.user = await api.getUser()
}
}
高级特性
插件系统
可以创建 Pinia 插件来扩展功能:
function myPiniaPlugin(context) {
context.store.$subscribe((mutation, state) => {
// 响应 store 变化
})
return { secret: 'the cake is a lie' }
}
const pinia = createPinia()
pinia.use(myPiniaPlugin)
服务端渲染 (SSR)
Pinia 支持 SSR,需要在 SSR 环境下进行适当配置。
与 Vuex 的比较优势
- 更简单的 API
- 更好的 TypeScript 支持
- 更轻量
- 模块化设计
- 无嵌套模块结构
Pina 已成为 Vue 3 官方推荐的状态管理解决方案,适合大多数中小型应用。
在 Pinia 中动态新增 State
在 Pinia 中,你可以动态地向 store 添加新的 state 属性,但需要注意一些方法和限制。
方法一:使用 $patch 动态添加 state
const store = useSomeStore()
// 动态添加新状态
store.$patch({
newState: '初始值'
})
方法二:直接赋值(不推荐)
const store = useSomeStore()
// 直接添加新属性(不推荐,可能失去响应性)
store.newState = '初始值'
方法三:使用 $state 替换整个状态
const store = useSomeStore()
// 替换整个状态对象
store.$state = {
...store.$state,
newState: '初始值'
}
最佳实践:在 store 定义时预留或使用 TypeScript 接口
interface MyStoreState {
existingState: string
[key: string]: any // 允许动态属性
}
export const useMyStore = defineStore('myStore', {
state: (): MyStoreState => ({
existingState: ''
})
})
注意事项
- 响应性:使用
$patch方法可以确保新添加的状态保持响应性 - TypeScript 支持:动态添加的属性在 TypeScript 中会报类型错误,除非使用扩展接口
- 开发工具:动态添加的状态在 Pinia 开发工具中可能不会立即显示
- 替代方案:考虑使用 Map 或动态对象作为 state,而不是直接添加属性
推荐模式
如果你需要高度动态的状态,可以考虑这种模式:
export const useDynamicStore = defineStore('dynamic', {
state: () => ({
dynamicStates: {} as Record<string, any>
}),
actions: {
addState(key: string, value: any) {
this.dynamicStates = {
...this.dynamicStates,
[key]: value
}
}
}
})
这样既保持了类型安全,又能动态管理状态。
浙公网安备 33010602011771号