Pinia 使用

安装 Pinia

npm install pinia

在 Vue 应用中挂载 Pinia

import { createPinia } from "pinia";
// 创建 pinia 实例
const pinia = createPinia();
createApp(App).use(router).use(pinia).mount("#app");

在 src 目录下面创建仓库目录 store,在该目录下面创建对应的仓库文件,注意名字一般是 useXXXStore

在仓库文件中,我们可以通过 defineStore 来创建一个 pinia 仓库,如下:

// 仓库文件
import { defineStore } from "pinia";

// 第二个参数支持两种风格:options api 以及 composition api
export const useCounterStore = defineStore("counter", {
  state: () => {
    return {
      num: 0,
    };
  },
});

创建的时候支持两种风格,选项式 API 以及组合式 API。

选项式风格

该风格基本上和之前的 Vuex 是非常相似的,只不过没有 mutation 了,无论是同步的方法还是异步的方法,都写在 actions 里面。

// 仓库文件
import { defineStore } from "pinia";

// 第二个参数支持两种风格:options api 以及 composition api
export const useCounterStore = defineStore("counter", {
  state: () => {
    return {
      num: 0,
    };
  },
  getters: {
    // 针对上面 state 的数据做一个二次计算
    // 可以看作是计算属性
    doubleCount: (state) => state.num * 2,
  },
  actions: {
    // 同步方法
    increment() {
      this.num++;
    },
    decrement() {
      this.num--;
    },
    // 异步方法
    async asyncIncrement() {
      // 等待 1 秒钟
      await new Promise((resolve) => setTimeout(resolve, 1000));
      this.increment();
    },
    async asyncDecrement() {
      await new Promise((resolve) => setTimeout(resolve, 1000));
      this.decrement();
    },
  },
});

在组件中使用仓库数据时,首先引入仓库方法,并执行该方法:

import { useCounterStore } from "@/store/useCounterStore.js";
const store = useCounterStore(); // 拿到仓库

如果是要获取数据,为了保持数据的响应式,应该使用 storeToRefs 方法。

import { storeToRefs } from "pinia";
// 接下来我们可以从仓库中解构数据出来
const { num, doubleCount } = storeToRefs(store);

如果是获取方法,直接从 store 里面解构出来即可。

// 从仓库将方法解构出来
const { increment, asyncIncrement, asyncDecrement } = store;

另外,仓库还提供了两个好用的 api:

  • store.$reset :重置 state
  • store.$patch:变更 state

组合式风格

组合式风格就和 Vue3 中的使用方法是一样的,通过 ref 或者 reactive 来定义仓库数据。

通过普通的方法来操作仓库数据。无论是数据还是方法最终需要导出出去。

通过 computed 来做 getter。

import { defineStore } from "pinia";
import { reactive, computed } from "vue";

// 引入其他仓库
import { useCounterStore } from "./useCounterStore.js";

export const useListStore = defineStore("list", () => {
  const counterStore = useCounterStore();
  // 组合 api 风格

  // 创建仓库数据,类似于 state
  const list = reactive({
    items: [
      {
        text: "学习 Pinia",
        isCompleted: true,
      },
      {
        text: "打羽毛球",
        isCompleted: false,
      },
      {
        text: "玩游戏",
        isCompleted: true,
      },
    ],
    counter: 100,
  });

  // 使用 vue 里面的计算属性来做 getters
  const doubleCounter = computed(() => {
    return list.counter * 2;
  });
  // 接下来我们再来创建一个 getter,该 getter 使用的是其他仓库的数据
  const otherCounter = computed(() => {
    return counterStore.doubleCount * 3;
  });

  // 添加新的事项
  function addItem(newItem) {
    list.items.push({
      text: newItem,
      isCompleted: false,
    });
  }

  // 切换事项对应的完成状态
  function completeHandle(index) {
    list.items[index].isCompleted = !list.items[index].isCompleted;
  }

  // 删除待办事项对应下标的某一项
  function deleteItem(index) {
    list.items.splice(index, 1);
  }

  return {
    list,
    doubleCounter,
    otherCounter,
    addItem,
    completeHandle,
    deleteItem,
  };
});

在一个仓库中,可以使用其他仓库的 getter 数据,两种风格都可以使用。

自定义插件

首先建议插件单独拿一个目录来存放,一个插件就是一个方法:

export function myPiniaPlugin1() {
  // 给所有的仓库添加了一条全局属性
  return {
    secret: "the cake is a lie",
  };
}

export function myPiniaPlugin2(context) {
  //   console.log(context);
  const { store } = context;
  store.test = "this is a test";
}

/**
 * 给特定的仓库来扩展内容
 * @param {*} param0
 */
export function myPiniaPlugin3({ store }) {
  if (store.$id === "counter") {
    // 为当前 id 为 counter 的仓库来扩展属性
    return {
      name: "my name is pinia",
    };
  }
}

/**
 * 重置仓库状态
 */
export function myPiniaPlugin4({ store }) {
  // 我们首先可以将初始状态深拷贝一份
  const state = deepClone(store.$state);
  store.reset = () => {
    store.$patch(deepClone(state));
  };
}

每个插件在扩展内容时,会对所有的仓库进行内容扩展,如果想要针对某一个仓库进行内容扩展,可以通过 context.store.$id 来指定某一个仓库来扩展内容。

插件书写完毕后,需要通过 pinia 实例对插件进行一个注册操作。

// 引入自定义插件
import {
  myPiniaPlugin1,
  myPiniaPlugin2,
  myPiniaPlugin3,
  myPiniaPlugin4,
} from "./plugins";

pinia.use(myPiniaPlugin1);
pinia.use(myPiniaPlugin2);
pinia.use(myPiniaPlugin3);
pinia.use(myPiniaPlugin4);

添加第三方插件

posted @ 2024-04-28 22:26  shmillly959  阅读(5)  评论(0编辑  收藏  举报