简介
Pinia 是 vue 生态中 vuex 的替代者,自从 vue3.0 出来之后,Pinia 越来越受欢迎。可以同时支持 vue2.0 和 vue3.0,代码编写也变得十分简单,完整支持 ts。
环境与安装
虽然同时支持 vue2.0 和 3.0,但是我们现在直接使用 vue3.0 的环境,来安装 Pinia。
npm install pinia
//or
yarn add pinia
Pinia 的使用
- 需要在 main.ts 中引入 pinia
import { createPinia } from 'pinia'
import App from './App.vue'
//创建pinia
const pinia = createPinia();
const app = createPinia(App);
app.use(pinia);
......
- 使用 pinia 创建一个 store。首先我们在文件目录中创建个状态管理的文件夹 store,放在/src 下,专门用来管理相关状态。同时创建 index.ts 文件。
import { defineStore } from "pinia";
export const mainStore = defineStore("main", {
state: () => {
return {};
},
getter: {},
actions: {},
});
//defineStore: 声明状态容器的名称main,名称唯一,不能重复;第二个参数是配置对象,里面含有配置相关内容。
//state:用来存储全局的状态,所有全局状态均在state里面定义。
//getter:类似于计算属性,可以计算状态变化,存在缓存
//actions:修改state中定义的状态数据
//下面会一一展开介绍
- 我们来为 state 添加一些全局状态的数据。
export const mainStore = defineStore("main", {
state: () => {
return {
newState: "Hello World",
count: 0,
tel: 12345677890,
};
},
getter: {},
actions: {},
});
接下来我们在组件中调用:
<template>
<div>{{ store.newState }}</div>
</template>
<script lang="ts" setup>
import { mainStore } from "../store/index";
const store = mainStore();
</script>
Pinia 改变状态的数据
修改状态数据,要比 vuex 简洁的多,比如我们定义一个记录点击次数的状态,count,每点击一次,count+1.
<template>
<div @click="handleclick">{{ store.count }}</div>
</template>
<script lang="ts" setup>
import { mainStore } from "../store/index";
const store = mainStore();
const handleclick = () => {
store.count++;
};
</script>
大家可能注意到了,为什么我没有采取解构的写法
<script lang="ts" setup>
const { count } = store;
</script>
这是因为,当你解构之后,解构的状态数据将不是响应式数据,当你修改 store 中的值之后,并不会及时发生变化。针对这个问题,pinia 提供了 storeToRefs()方法
import { storeToRefs } from "pinia";
这样就可以使用解构写法
<script lang="ts" setup>
const { count } = storeToRefs(store);
</script>
那么如何一次性修改多条数据呢?我们还用上文的 handleclick()方法,这时候我们用到了 pinia 的$patch。
const handleclick = () => {
store.$patch({
count: store.count + 1,
newState: `${store.newState} hello pinia!`,
});
};
看到这里有没有觉得这样的代码很熟悉,既然可以传递对象,当然也可以传递一个函数。
const handleclick = () => {
store.$patch((state) => {
state.count++;
state.newState = `${state.newState} hello pinia!`;
});
};
// state 指的就是store对象
还记得上文中actions对象吗?既然解释了它是为了修改状态而存在的,那么为什么我们现在修改状态没用到呢?那是因为actions可以处理更为复杂的修改逻辑。
actions: {
changeState(){
this.count++;
this.newState='hello pinia!'
}
}
调用方式是这样的,依旧使用 handleclick()方法
const handleclick = () => {
store.changeState();
};
Pinia 中的 getters
如果我们想在拿到值的时候,对值进行一些处理。我们可以在 getters 中实现。
//比如我们要把tel中间4位隐藏。
getters:{
hideTel(state){
return state.tel.toString().replace(/^(\d{3})\d{4}(\d{4})$/, '$1****$2')
}
}
调用方法:
<template>
<div>{{ hideTel }}</div>
</template>
<script lang="ts" setup>
import { mainStore } from "../store/index";
import { storeToRefs } from "pinia";
const store = mainStore();
const { hideTel } = storeToRefs(store);
</script>
getters 的缓存特性,就是当你在值没有变化的情况下 多次调用 hideTel(),实际只会调用一次,只有当tel的值发生改变的时候,才会再次调用。
Pinia 中 store 之间相互调用
我们在 store 文件夹下再创建个 index2.ts,作为另一个 store 容器,那么如何与 index.ts 的 store 之间相互调用呢?
//首先 我们需要引入index.ts
import { mainStore } from "./index.ts";
export const main2Store = defineStore("main2", {
state: () => {
return {
newStore: "hello pinia",
newCount: 0,
};
},
getter: {},
actions: {
//这里我们写一个调用方法,就实现了相互调用。
getCount() {
console.log(mainStore.count);
this.newCount = mainStore.count;
},
},
});
不足之处,多多指教。