用官网的一句话来说:Pinia
是 Vue
的专属状态管理库
Pinia
就是为vue3
而生,当然也支持vue2
Pinia
在使用上更简单,更适合同组合式api
和Typescript
一同使用
npm install pinia
# or
yarn add pinia
在vue
的main.js
中使用
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from "pinia";
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
store
通过defineStore()
函数进行定义,可以定义多个store
,但是定义每个store的时候必须要传入一个唯一的id作为defineStore()
的第一个参数
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({ user: {
name: '张三'
} }),
getters: {
userName: (state) => state.user.name,
},
actions: {
setName(name) {
this.user.name = name
},
},
})
也可以定义组合式api
形式的store
ref()
对应 state
computed()
对应 getters
function()
对应 actions
export const useUserStore = defineStore('user', () => {
const user = ref({
name: '张三'
})
const userName = computed(() => {
return user.value.name
})
function setName(name) {
user.value.name = name
}
return { user, userName, setName }
})
<template>
<div>
<div>用户名: {{userName}}div>
<button @click="handleClick">设置用户名button>
div>
template>
<script lang="ts" setup>
import {useUserStore} from "../stores";
import {storeToRefs} from "pinia";
const store = useUserStore()
// 将store中的state或者getter转为响应式变量
const {userName} = storeToRefs(store)
// 将store中的action解构出来
const {setName} = store
const handleClick = () => {
increment('李四')
}
script>
<style scoped lang="scss">
style>
state
在store里面是一个返回初始状态的函数
import { defineStore } from 'pinia'
interface User {
name: string
sex: number
}
const useUserStore = defineStore('user', {
// 如果使用的是ts,使用箭头函数可以自动推理出state返回状态的类型
state: () => {
return {
isTest: false
count: 1,
userList: [] as User[],
}
},
})
const store = useUserStore()
store.count++
调用$reset()
重置之后,state里的状态会全部恢复为初始值
store.$reset()
除了上面store.count++
直接修改这种方式,还可以使用$patch
函数同时修改多个状态
store.$patch({
count: store.count + 1,
isTest: true,
})
// 传入一个函数
store.$patch((state) => {
state.count = state.count + 1,
state.isTest = true
})
通过store
的$subscribe
函数可以监听state 的变化
store.$subscribe((mutation, state) => {
console.log(mutation);
console.log(state);
})
mutation
为修改state
的方式,主要有三个属性
type
: direct
| patch object
| patch function
direct
:通过等号直接赋值的方式修改state的状态时patch object
:通过$patch函数修改并且传入的参数为一个对象时patch function
:通过$patch函数修改并且传入的参数为一个函数时storeId
:定义当前store
时传入的唯一id
payload
:type
为patch object
时,传入的对象getter
完全等同于store
中state
的计算属性,推荐使用箭头函数来定义getter
,并将state
作为第一个参数。
在getter
内部可以通过this
方位到整个store
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({ user: {
name: '张三'
} }),
getters: {
userName: (state) => state.user.name,
},
})
export const useUserStore = defineStore('user', () => {
const user = ref({
name: '张三'
})
// 相当于getter中定义userName
const userName = computed(() => {
return user.value.name
})
return { user, userName }
})
访问getter时不能传递任何参数,但是可以通过使getter返回一个接收参数的函数的形式来接收参数
getters: {
userName: (state) => {
return (before) => before + state.user.name
},
}
访问带参getter
<script>
export default {
setup() {
const store = useUserStore()
return { getUserName: store.userName }
},
}
script>
<template>
<p>{{ getUserName('Hi,') }}p>
template>
action
相当于组件的method
,在store
中定位为一个函数(可以是异步函数),主要用于处理业务逻辑,在action
内部同样可以通过this
访问的整个store的属性
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({ user: {
name: '张三'
} }),
actions: {
setName(name) {
this.user.name = name
},
},
})
export default {
setup() {
const store = useUserStore()
store.setName('李四')
return { }
},
}
通过store
的$onAction()
函数来监听action执行的相关信息.
$onAction()
接收两个参数,第一个参数为一个钩子函数,会在action
执行之前调用此钩子函数;第二个参数是一个boolean
类型的参数,当前组件被销毁是传入的钩子函数是否继续执行,默认为false
const store = useUserStore()
store.$onAction(({name, store, args, after, onError})=>{
console.log(`${name} 函数准备开始执行`)
console.log(`${name} 函数的参数为:${args}`)
after(() => {
console.log(`${name} 函数执行完成`)
})
})
// 手动删除监听器
unsubscribe()