一文带你搞懂Vue3中Pinia的使用
BDawn 人气:4什么是Pinia
用官网的一句话来说:Pinia 是 Vue的专属状态管理库
Pinia就是为vue3而生,当然也支持vue2
Pinia VS Vuex
Pinia在使用上更简单,更适合同组合式api和Typescript一同使用
安装Pinia
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')
使用Pinia
定义store
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 } })
在vue组件中使用store
<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>
Pinia之state
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[], } }, })
访问state
const store = useUserStore() store.count++
重置store中的state
调用$reset()重置之后,state里的状态会全部恢复为初始值
store.$reset()
修改state中的状态
除了上面store.count++直接修改这种方式,还可以使用$patch函数同时修改多个状态
store.$patch({ count: store.count + 1, isTest: true, }) // 传入一个函数 store.$patch((state) => { state.count = state.count + 1, state.isTest = true })
订阅state
通过store的$subscribe函数可以监听state 的变化
store.$subscribe((mutation, state) => { console.log(mutation); console.log(state); })
mutation为修改state的方式,主要有三个属性
1.type: direct | patch object | patch function
- direct:通过等号直接赋值的方式修改state的状态时
- patch object :通过$patch函数修改并且传入的参数为一个对象时
- patch function:通过$patch函数修改并且传入的参数为一个函数时
2.storeId:定义当前store时传入的唯一id
3.payload:type为patch object 时,传入的对象
Pinia之getter
getter完全等同于store中state的计算属性,推荐使用箭头函数来定义getter,并将state作为第一个参数。
在getter内部可以通过this方位到整个store
定义getter
import { defineStore } from 'pinia' export const useUserStore = defineStore('user', { state: () => ({ user: { name: '张三' } }), getters: { userName: (state) => state.user.name, }, })
组合式api的形式定义getter
export const useUserStore = defineStore('user', () => { const user = ref({ name: '张三' }) // 相当于getter中定义userName const userName = computed(() => { return user.value.name }) return { user, userName } })
向getter传参
访问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>
Pinia之action
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 }, }, })
访问action
export default { setup() { const store = useUserStore() store.setName('李四') return { } }, }
订阅action
通过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()
加载全部内容