简言
这次说一下状态管理工具pinia。为什么用pinia?因为它小,比vuex4简单些。Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。
话不多说,不玩虚的,这就4vue,莱茨狗! ——ZSK666
配置
安装
yarn add pinia
# 或者使用 npm
npm install pinia
引入
src下新建store文件夹,index.ts配置如下
import { createPinia, defineStore } from 'pinia'
const pinia = createPinia()
export const useStore = defineStore('main', {
// 类似data
state: () => {
return {
userInfo: undefined,
token: undefined,
}
},
// 类似计算属性
getters: {
},
// 类似methods
actions: {
}
})
// 返回实例
export default pinia
main.ts vue实例新增pinia。
这样的话,一个简单的pinia就配置好了。
使用
创建store
store对象,使用defineStore(name,obj | fn)方法创建,它传入两个参数,第一个参数是store名,要求是独一无二的名字;第二个参数可以传入options对象(就是包含state、actions 与 getters 属性的 对象),或者setup函数(类似setup函数写法的函数,返回的参数中,ref就是state,computed就是getters,function就是actions)。
先来介绍下重要的三个属性:state、getters、actions(pinia没有mutions)。
- state:在 Pinia 中,state 被定义为一个返回初始状态的函数。这使得 Pinia 可以同时支持服务端和客户端。
- getters:Getter 完全等同于 store 的 state 的计算值。可以通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数。
- Action: Action 相当于组件中的 method。它们可以通过 defineStore() 中的 actions 属性来定义,并且它们也是定义业务逻辑的完美选择。可以写同步,也可以写异步。
下面是简单的store示例:
import { defineStore } from 'pinia'
export const useStore = defineStore('main', {
// 类似data
state: () => {
return {
userInfo: JSON.parse(localStorage.getItem('userInfo')) || undefined,
token: undefined,
num:1,
}
},
// 类似计算属性
getters: {
getNum2:(state)=> state.num * 2
},
// 类似methods
actions: {
setUserInfo(info = null) {
this.userInfo = info || undefined
console.log(info);
localStorage.setItem('userInfo', JSON.stringify(info))
}
}
})
使用store
在要使用的页面中引入上面创建的store。
<script lang="ts" setup>
import { useStore } from "@/store/index";
// 定义数据
const store = useStore();
//使用 action
store.setUserInfo({
name: "zsk",
info: "balabala...",
} as any);
</script>
其他页面使用也是类似,引入store实例,直接使用。
<template>
<div class="container">我是detail</div>
<div>
<div>
{{ store.userInfo }}
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, toRefs, onBeforeMount, onMounted } from "vue";
// 使用pinia
import { useStore } from "@/store";
const store = useStore();
console.log(store, store.userInfo);
</script>
<style lang="scss" scoped></style>
除了用 store.count++ 直接改变 store,你还可以调用 $patch 方法。它允许你用一个 state 的补丁对象在同一时间更改多个属性:
store.$patch({
token:'xxx...'
num: 10,
})
返回的store,不能直接解构state里的属性,不然会失去响应性,pinia提供了storeToRefs方法,它将为每一个响应式属性创建引用。当你只使用 store 的状态而不调用任何 action 时,它会非常有用。
改进上面的代码:
<template>
<div class="container">我是detail</div>
<div>
<div>
{{ store.userInfo }}
</div>
<div>userInfo:{{ userInfo }}</div>
<div>token:{{ token }}</div>
<div>num:{{ num }}</div>
<button @click="change">变更</button>
</div>
</template>
<script lang="ts" setup>
import { reactive, toRefs, onBeforeMount, onMounted } from "vue";
// 使用pinia
import { useStore } from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
console.log(store, store.userInfo);
const { userInfo, token, num } = storeToRefs(store);
const change = () => {
store.$patch({
num: 10,
token: "xxx...",
});
};
</script>
<style lang="scss" scoped></style>
效果
结语
pinia的基础使用就结束了,和vue相比,特点是轻量化,很适合个人项目或小型项目使用。