vue3使用pinia管理状态
Pinia
pinia 是一款新的vue3的状态管理库,完整的typescript支持。
安装
yarn add pinia
# or npm
npm install pinia
创建根store并且引用到app上
import { createPinia } from 'pinia'
app.use(createPinia())
定义Store
使用defineStore
定义store
,第一个参数必须是全局唯一的id,可以使用Symbol
import { defineStore } from 'pinia'
// 第一个参数必须是全局唯一
export const useStore = defineStore('main', {
})
使用store
在setup
中使用useStore
创建store
实例
<script setup>
import {useStore} from '@/stores/counter'
const store = useStore()
....
</script>
状态State
定义状态
import { defineStore } from 'pinia',
const useCounterStore = defineStore('counterStore', {
state: () => ({
counter: 0
})
})
定义强状态
import { defineStore } from 'pinia',
interface ICounterStoreState{
counter: number
}
const useCounterStore = defineStore('counterStore', {
state: ():ICounterStoreState => ({
counter: 0
})
})
使用和重置状态
const store = useCounterStore()
// 使用
store.counter++
// 重置
store.$reset()
改变状态
store.$patch({
counter: store.counter + 1,
name: 'Abalam',
})
替换状态
store.$state = { counter: 666, name: 'Paimon' }
计算属性Getters
Getter 完全等同于 Store 状态的计算值,可以用 defineStore() 中的 getters 属性定义
export const useStore = defineStore('main', {
state: () => ({
counter: 0,
}),
getters: {
doubleCount: (state) => state.counter * 2,
},
})
传递参数到getters
Getter 是计算属性,也可叫只读属性,因此不可能将任何参数传递给它们。但是可以从 getter 返回一个函数以接受任何参数
export const useStore = defineStore('main', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})
访问其他store的getters
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => ({
// ...
}),
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
动作Actions
动作相当于组件中的方法,可以使用 defineStore() 中的 actions 属性来定义,它们非常适合定义业务逻辑
import { mande } from 'mande'
const api = mande('/api/users')
export const useUsers = defineStore('users', {
state: () => ({
userData: null,
// ...
}),
actions: {
async registerUser(login, password) {
try {
this.userData = await api.post({ login, password })
showTooltip(`Welcome back ${this.userData.name}!`)
} catch (error) {
showTooltip(error)
// let the form component display the error
return error
}
},
},
})
访问其他store的actions
import { useAuthStore } from './auth-store'
export const useSettingsStore = defineStore('settings', {
state: () => ({
preferences: null,
// ...
}),
actions: {
async fetchUserPreferences() {
const auth = useAuthStore()
if (auth.isAuthenticated) {
this.preferences = await fetchPreferences()
} else {
throw new Error('User must be authenticated')
}
},
},
})
插件
假设需要在stroe中使用router,就需要使用到pinia的插件机制扩展store的api
pinia.d.ts
import 'pinia'
import { Router} from 'vue-router'
declare module 'pinia' {
export interface PiniaCustomProperties {
$router: Router,
}
}
定义插件
import { createPinia } from 'pinia'
import { App} from "vue";
import { router } from '@/routers'
const pinia = createPinia()
pinia.use(({ store }) => {
store.$router = router
})
app.use(pinia)
在action中使用插件定义的pai
import { defineStore } from 'pinia'
import { RouteLocationNormalized } from 'vue-router'
export const useApplicationStore = defineStore('application', {
state: () => (
...
),
actions:{
toHome(){
this.$router.push('/home')
}
}
})
推荐结构
stores
index.ts
use.store.ts
app.store.ts …
stores/index.ts
import { createPinia } from 'pinia'
import { App} from "vue";
const pinia = createPinia()
export function setupPinia(app: App){
pinia.use(({ store }) => {
... 这里安装插件
})
app.use(pinia)
}
export * from './use.store.ts'
export * from './app.store.ts'
何时使用状态管理器
全局都会使用到的状态使用状态管理器,比如用户信息、主题、权限等等