介绍
Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队讨论中的许多想法。最终,我们意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分内容,并决定实现它 取而代之的是新的建议。
与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的规范,提供了 Composition-API 风格的 API,最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持。
从官方文档可以看出,pinia 可以说是 vuex 5
用过vuex的可以看下 省流版 对比
- 由以前的5大核心概念变成了3大核心概念(
state、getters、actions) - 废弃了
mutations在actions里也能进行异步操作 - 废弃了
modules的模块化以及namespaced命名空间,现在每个store都是一个独立的空间 - 结合 vue3
Composition-API可以更加方便的使用,无需借用 map辅助函数
接下来带大家体验一下pinia~
安装
npm install pinia
引入
main.ts中引入
import { createApp } from "vue";
import App from "./App.vue";
import { createPinia } from "pinia";
const pinia = createPinia();
const app = createApp(App);
app.use(pinia);
app.mount("#app");
创建 store/index.ts
state的使用
import { defineStore } from "pinia";
// 通过defineStore创建一个store,useUserStore 就是一个store对象,命名自由
// defineStore的第一个参数是必填的,相当于modules,将每个store区分开来
export const useUserStore = defineStore("user", {
state: () => {
return {
name: "狮子",
age: 18,
};
},
});
在组件中使用
<script setup lang="ts">
import { storeToRefs } from "pinia";
import { useUserStore } from "@/store/index";
const userStore = useUserStore();
const { name, age } = storeToRefs(userStore);
userStore.$patch({
age: userStore.age + 1,
});
// 别学我 anyScript 哈
userStore.$patch((state:any) => {
state.name = "这货不是狮子";
});
</script>
<template>
<div>{{ name }} - {{ age }}</div>
<div>{{ userStore.name }} - {{ userStore.age }}</div>
</template>
pinia 提供了 storeToRefs,使得从 userStore 里解构的时候 name、age 具有响应式,而不能直接使用 const { name, age } = userStore
pinia 还提供了 $patch 来改变 state 状态,可以接收 对象 和 函数 形式
getters的使用
export const useUserStore = defineStore("user", {
state: () => {},
getters: {
// getUserIntro(state) {
// return `${state.name}今年已经${state.age}了`;
// },
getUserIntro: (state) => `${state.name}今年已经${state.age}了`,
},
});
在组件中使用
<script setup lang="ts">
import { storeToRefs } from "pinia";
import { useUserStore } from "@/store/index";
const userStore = useUserStore();
const { getUserIntro } = storeToRefs(userStore);
</script>
<template>
<div>{{ getUserIntro }}</div>
<div>{{ userStore.getUserIntro }}</div>
</template>
actions的使用
export const useUserStore = defineStore("user", {
state: () => {},
getters: {},
actions: {
// this指向的就是useUserStore
GrowUp(name: string, age: number) {
this.name = name;
this.age = age;
},
GrowUpAsync(name: string, age: number) {
setTimeout(() => {
this.name = name;
this.age = age;
}, 1000);
},
},
});
在组件中使用
<script setup lang="ts">
import { storeToRefs } from "pinia";
import { useUserStore } from "@/store/index";
const userStore = useUserStore();
const { name, age, getUserIntro } = storeToRefs(userStore);
const change = () => {
userStore.GrowUp("小狮子", 19);
};
const changeA = () => {
userStore.GrowUpAsync("老狮子", 81);
};
</script>
<template>
<div>{{ name }} - {{ age }}</div>
<div>{{ userStore.name }} - {{ userStore.age }}</div>
<div>{{ getUserIntro }}</div>
<div>{{ userStore.getUserIntro }}</div>
<button type="button" @click="change">同步改变</button>
<button type="button" @click="changeA">异步改变</button>
</template>
持久化
安装
npm install pinia-plugin-persistedstate
注册
import { createApp } from "vue";
import App from "./App.vue";
import { createPinia } from "pinia";
import piniaPluginPersistedstate from "pinia-plugin-persistedstate"; // 引入
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate); // 使用
const app = createApp(App);
app.use(pinia);
app.mount("#app");
使用
export const useUserStore = defineStore("user", {
// 设置 persist: true,就是把整个 useUserStore 本地化,生成key为user、value为state值的 localStorage
// persist: true,
// 需要个性化设置
persist: {
// 存储的key,默认为当前 StoreId
key: "storekey",
// 存储容器,默认为 localStorage 可选 sessionStorage
storage: window.sessionStorage,
// 指定需要存储的数据,使用逗号隔开,[] 表示不持久化任何状态,undefined 或 null 表示持久化整个 state。
paths: ["name"],
},
state: () => {
return {
name: "狮子",
age: 18,
};
},
});
感受
个人感受是比 vuex 香的,配合 Composition-API 方便太多了(除非你不用 setup),更方便的模块化也是我这个强迫症福音,赶紧用起来吧!