摸鱼时间学习了pinia,比vuex香~

155 阅读2分钟

介绍

Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队讨论中的许多想法。最终,我们意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分内容,并决定实现它 取而代之的是新的建议。

与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的规范,提供了 Composition-API 风格的 API,最重要的是,在与 TypeScript 一起使用时具有可靠的类型推断支持。

从官方文档可以看出,pinia 可以说是 vuex 5

用过vuex的可以看下 省流版 对比

  • 由以前的5大核心概念变成了3大核心概念stategettersactions
  • 废弃了 mutationsactions 里也能进行异步操作
  • 废弃了 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),更方便的模块化也是我这个强迫症福音,赶紧用起来吧!