前言
在开发Vue3时发现越来越多的人开始使用Pinia,它的好处就不说了,官网很详细。
本文的目的是帮助自己学习Pinia
安装
在之前的一篇文章中我已经写过如何安装它,也可以直接看官网的安装教程,这里不过多阐述
使用
- 一种常规的使用方法就是类似于
vuex,如:
// test.ts
import { defineStore } from 'pinia';
export const useTestStore = defineStore('test', {
state: () => {
return {
name: 'xiaoming',
age: 18
}
}
});
- 类似Vue3一样的写法
// test.ts
import { defineStore } from 'pinia';
import { ref } from 'vue';
export const useTestStore = defineStore('test', () => {
const name = ref('xiaoming');
const age = ref(18);
return {
name,
age
}
});
修改state的5种方式
- 直接用对象修改
$patch(args)$patch(() => args)$stateactions内的方法修改
<template>
<p>name: {{ test.name }}, age: {{ test.age }}</p>
<button class="px-4 border-2 border-solid border-black" @click="changeInfo">change</button>
</template>
<script setup lang="ts">
import { useTestStore } from '@/piniaStore/test';
const test = useTestStore()
const changeInfo = () => {
// 1. 直接修改
test.name = 'laoli';
// 2. $patch
// test.$patch({
// name: 'laoli'
// });
// 3. $patch,用于一些条件的判断
// test.$patch((state) => {
// state.name = 'laoli';
// });
// 4. $state,必须全部都要赋值,不能单独一个
// test.$state = {
// name: 'laoli',
// age: 18
// }
// 5. pinia的actions方式
// test.setName('laoli');
}
</script>
其中第5种方式的actions写法为:
// test.ts
import { defineStore } from 'pinia';
export const useTestStore = defineStore('test', {
// ...
actions: {
setName(name: string) {
this.name = name;
}
}
});
解构
<template>
<p>name: {{ test.name }}, age: {{ test.age }}</p>
<p>name: {{ name }}, age: {{ age }}</p>
<button class="px-4 border-2 border-solid border-black" @click="changeInfo">change</button>
</template>
<script setup lang="ts">
import { useTestStore } from '@/piniaStore/test';
import { storeToRefs } from 'pinia';
// import { toRefs } from 'vue';
const test = useTestStore()
const { name, age } = storeToRefs(test)
// const { name, age } = toRefs(test) // 也可以使用vue3的toRefs
const changeInfo = () => {
// 1. 还是原对象改变
// test.name = 'laoli';
// 2. 直接使用结构对象改变
name.value = 'laoli';
}
</script>
getters & actions用法
import { defineStore } from 'pinia';
interface User {
name: string;
age: number;
}
const asyncSetName = () => {
return new Promise<User>((resolve) => {
setTimeout(() => {
resolve({
name: 'laowang',
age: 20
})
}, 2000);
})
}
export const useTestStore = defineStore('test', {
state: () => {
return {
name: 'xiaoming',
age: 18
}
},
getters: {
personInfo({ name, age }) {
return `name: ${name}, age: ${age}`;
}
},
actions: {
async setName() {
const { name, age } = await asyncSetName();
this.name = name;
this.age = age;
}
}
});
公共方法
$subscribe:state改变时触发该函数内的回调函数$reset:state恢复原始值$onAction:actions改变时触发该函数内的回调函数
<template>
<p>name: {{ test.name }}, age: {{ test.age }}</p>
<button class="px-4 border-2 border-solid border-black" @click="changeInfo">change</button>
<br>
<button class="px-4 border-2 border-solid border-black" @click="onReset">reset</button>
</template>
<script setup lang="ts">
import { useTestStore } from '@/piniaStore/test';
const test = useTestStore()
const changeInfo = () => {
test.setName();
}
// state改变时触发该回调函数
test.$subscribe((args, state) => {
console.log(args, state);
});
// actions改变时触发该回调函数
test.$onAction((args) => {
console.log(args);
});
const onReset = () => {
// 恢复到原来的状态
test.$reset();
}
</script>
持久化
- 使用
$subscribe监听state变化 - 一开始加载时读取数据
import type { PiniaPluginContext } from 'pinia';
import { createApp, toRaw } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
interface PluginOptions {
key: string;
}
const setData = (key: string, value: unknown) => {
localStorage.setItem(key, JSON.stringify(value));
}
const getData = (key: string) => {
let value = localStorage.getItem(key);
let parseVal = {}
try {
parseVal = JSON.parse(value || '{}');
} catch {
console.error('parse error');
}
return parseVal
}
const createPlugin = (options: PluginOptions) => {
const { key } = options;
return (context: PiniaPluginContext) => {
const { store } = context
// 保存state值
store.$subscribe(() => {
setData(key, toRaw(store.$state));
});
// 获取state值
const state = getData(key);
return state;
}
}
const app = createApp(App);
const store = createPinia();
store.use(createPlugin({
key: 'testPlugin'
}));
app.use(store);
app.mount('#app');
问题:如果使用setup的方式声明变量,暂时还不知道如何取数据才能拿到所有的$state,有知道的告诉我一下