状态管理
Pinia基础
安装Pinia
bash
npm install pinia创建Store
javascript
// stores/counter.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
// state
const count = ref(0)
// getters
const doubleCount = computed(() => count.value * 2)
// actions
function increment() {
count.value++
}
function decrement() {
count.value--
}
async function fetchCount() {
// 异步操作
const response = await fetch('/api/count')
const data = await response.json()
count.value = data.count
}
return { count, doubleCount, increment, decrement, fetchCount }
})使用Store
vue
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
// 读取state
console.log(counter.count)
// 读取getters
console.log(counter.doubleCount)
// 调用actions
counter.increment()
</script>
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="counter.increment">+1</button>
</div>
</template>解构Store
storeToRefs
vue
<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
// 解构state和getters(保持响应性)
const { count, doubleCount } = storeToRefs(counter)
// 解构actions(直接解构)
const { increment, decrement } = counter
</script>持久化
安装插件
bash
npm install pinia-plugin-persistedstate配置持久化
javascript
// stores/index.js
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
export default pinia使用持久化
javascript
// stores/user.js
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useUserStore = defineStore('user', () => {
const token = ref('')
const userInfo = ref(null)
function setToken(newToken) {
token.value = newToken
}
function setUserInfo(info) {
userInfo.value = info
}
function logout() {
token.value = ''
userInfo.value = null
}
return { token, userInfo, setToken, setUserInfo, logout }
}, {
persist: {
key: 'my-user-store',
storage: localStorage,
paths: ['token', 'userInfo']
}
})组合多个Store
javascript
// stores/index.js
import { useCounterStore } from './counter'
import { useUserStore } from './user'
export function useRootStore() {
const counter = useCounterStore()
const user = useUserStore()
function resetAll() {
counter.$reset()
user.$reset()
}
return {
counter,
user,
resetAll
}
}订阅状态变化
vue
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
// 订阅state变化
counter.$subscribe((mutation, state) => {
console.log('类型:', mutation.type)
console.log('storeId:', mutation.storeId)
console.log('新状态:', state)
// 持久化到本地存储
localStorage.setItem('counter', JSON.stringify(state))
})
// 订阅actions
counter.$onAction(({ name, args, after, onError }) => {
console.log(`Action ${name} 被调用,参数:`, args)
after((result) => {
console.log(`Action ${name} 完成,结果:`, result)
})
onError((error) => {
console.error(`Action ${name} 出错:`, error)
})
})
</script>插件开发
javascript
// plugins/piniaLogger.js
export function piniaLogger({ store }) {
store.$onAction(({ name, args, after, onError }) => {
console.log(`[${store.$id}] ${name} 开始`, args)
after((result) => {
console.log(`[${store.$id}] ${name} 完成`, result)
})
onError((error) => {
console.error(`[${store.$id}] ${name} 失败`, error)
})
})
}
// 使用插件
const pinia = createPinia()
pinia.use(piniaLogger)