Pinia是一个用于Vue的状态管库, 类似于Vuex, 是Vue的另外一种状态管理方案;
Pinia优势
以Vue3为主
yarn add pinia
# or with npm
npm install pinia
import { createPinia } from 'pinia'
app.use(createPinia())
import { defineStore } from 'pinia';
interface todosModel {
id: number;
text: string;
isFinished: boolean;
}
export const useCountDownStore = defineStore('countDown', {
state: () => ({
num: 1,
todos: [] as todosModel[],
}),
getters: {},
actions: {
},
});
{{ countDownStore.num }}
因为pinia抛弃了vuex中的mutations, 所以所有的方法都放在了actions中
// 方法1:
// 在任何地方直接更改
countDownStore.num++
// 方法2
// 在countDown.ts的actions中新增如下函数
actions: {
addOne(text: number) {
if (text) {
this.num = text ? (this.num + text) : this.num + 1;
}
}
}
// 方法3
// 调用countDownStore的$patch方法,该方法可以同时修改多条数据 如:
countDownStore.$patch({ num: countDownStore.num + 1 })
// 同时$patch接受传递函数, 该方法接受复杂数据修改
countDownStore.$patch((state) => {
state.num++;
state.todos.push({
id: 1,
text: 'hello, pinia!',
isFinished: false
})
})
// 方法4
// 直接整个更改state
countDownStore.$state = {
num: 666,
todos: [
{id: 1, text: '全局更改state', isFinished: false}
]
}
其实使用getters和直接使用state一样,类似于一个变量
state: () => ({
card: '411000199001010203'
}),
getters: {
hiddenCard(state): string {
return state.card.replace(/(.{4}).*(.{2})/, "$1********$2")
}
}
在.vue中使用
<template>
<p>{{ countDownStore.hiddenCard }}</p>
<template>
<script setup lang="ts">
import { useCountDownStore } from '@/store/modules/countDown';
const countDownStore = useCountDownStore();
console.log(countDownStore.hiddenCard);
// 4110********03
</script>
在vue文件中解构pinia中的state会出现丢失响应式的问题,可以通过pinia出的 storeToRefs去进行解构可以保持变量的响应式
state: () => {
return {
num: 1
}
}
import { storeToRefs } from 'pinia';
const countDownStore = useCountDownStore();
const { num } = storeToRefs(countDownStore);
// 这个时候num依旧保持响应式不会丢失
如以下有两个模块
「countDown.ts」, 「counter.ts」
countDown.ts
state: () => ({
num: 1,
}),
actions: {
changeNum(num: number): void {
this.num = num;
},
},
counter.ts
import { useCountDownStore } from './countDown';
state: () => {
return {
count: 1,
};
},
actions: {
increment() {
const countDownStore = useCountDownStore();
countDownStore.changeNum(20);
this.count++;
},
},
在*.vue中调用 actions中的increment方法, 可以同时更改两个模块中的数据, 不需要像vuex一样还需要使用root:true
import { defineStore } from 'pinia';
interface stateModel {
countTime: number;
isStart: boolean;
timeId: ReturnType<typeof setInterval> | null;
}
export const useCountDownStore = defineStore('countDown', {
state: (): stateModel => ({
// 倒计时时间
countTime: 10,
// 是否开始倒计时
isStart: false,
// setInterval
timeId: null,
}),
getters: {
getBtnText(): string {
return !this.isStart ? '获取验证码' : `${this.countTime}s`;
},
},
actions: {
clear() {
this.timeId && window.clearInterval(this.timeId);
},
stopDown() {
this.isStart = false;
this.clear();
this.timeId = null;
},
async startDown() {
if (this.isStart || !!this.timeId) {
return;
}
this.isStart = true;
this.timeId = setInterval(() => {
if (this.countTime === 1) {
this.stopDown();
this.countTime = 10;
} else {
this.countTime -= 1;
}
}, 1000);
},
},
});
在*.vue中使用如下
<template>
<button type="button" :disabled="isStart" @click="countDownStore.startDown">
{{ getBtnText }}
</button>
</template>
<script setup lang="ts">
import { useCountDownStore } from '@/store/modules/countDown';
import { storeToRefs } from 'pinia';
const countDownStore = useCountDownStore();
// 对getters, state中的数据进行响应式解构
const { num, isStart, getBtnText } = storeToRefs(countDownStore);
</script>
以上就是pinia的入门操作