6. Pinia:Pinia 插件开发

发布于:2024-07-16 ⋅ 阅读:(141) ⋅ 点赞:(0)

Pinia 插件允许我们扩展 Pinia 的功能,可以添加自定义的行为或修改已有的行为。插件通常用于添加共享的逻辑、全局状态处理或集成第三方库。

插件的基本原理

  1. 安装插件: 使用 pinia.use() 方法安装插件。
  2. 扩展功能: 插件可以通过返回一个对象来扩展 store 的属性或方法。
  3. 生命周期钩子: 插件可以利用 onActiononPatch 等钩子来监听 store 的行为。

开发过程

创建一个简单的 Pinia 插件

首先,我们创建一个简单的日志插件,它会记录每个 store 的操作:

// plugins/logger.js
export function loggerPlugin({ store }) {
  store.$onAction(({ name, args, after, onError }) => {
    console.log(`Action "${name}" with args:`, args);
    after((result) => {
      console.log(`Action "${name}" result:`, result);
    });
    onError((error) => {
      console.error(`Action "${name}" failed:`, error);
    });
  });
}

安装插件

在 Vue 应用中使用这个插件:

// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import { loggerPlugin } from './plugins/logger';

const app = createApp(App);
const pinia = createPinia();

pinia.use(loggerPlugin);

app.use(pinia);
app.mount('#app');

示例一:日志插件

我们先定义一个简单的 store 来演示日志插件的效果:

// stores/counter.js
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
  }),
  actions: {
    increment() {
      this.count++;
    },
    decrement() {
      this.count--;
    },
  },
});

在组件中使用这个 store:

<template>
  <div>
    <p>Count: {{ counterStore.count }}</p>
    <button @click="counterStore.increment">Increment</button>
    <button @click="counterStore.decrement">Decrement</button>
  </div>
</template>

<script>
import { useCounterStore } from '@/stores/counter';

export default {
  setup() {
    const counterStore = useCounterStore();
    return { counterStore };
  },
};
</script>

运行应用时,每次调用 incrementdecrement 方法,都会在控制台中看到日志输出。

示例二:持久化插件

接下来,我们创建一个持久化插件,它会将 store 的状态保存在 localStorage 中,并在应用启动时恢复状态:

// plugins/persist.js
export function persistPlugin({ store }) {
  const storedState = localStorage.getItem(store.$id);
  if (storedState) {
    store.$patch(JSON.parse(storedState));
  }

  store.$subscribe((mutation, state) => {
    localStorage.setItem(store.$id, JSON.stringify(state));
  });
}

在 main.js 中安装这个插件:

// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import { loggerPlugin } from './plugins/logger';
import { persistPlugin } from './plugins/persist';

const app = createApp(App);
const pinia = createPinia();

pinia.use(loggerPlugin);
pinia.use(persistPlugin);

app.use(pinia);
app.mount('#app');

现在,counter store 的状态会自动保存到 localStorage 中,并在应用重新加载时恢复。

示例三:自定义 getter 插件

创建一个自定义 getter 插件,它会为每个 store 添加一个 uppercaseState 的 getter,将 store 中所有字符串类型的 state 转换为大写:

// plugins/uppercase.js
export function uppercasePlugin({ store }) {
  store.uppercaseState = computed(() => {
    const uppercased = {};
    for (const key in store.$state) {
      if (typeof store.$state[key] === 'string') {
        uppercased[key] = store.$state[key].toUpperCase();
      }
    }
    return uppercased;
  });
}

在 main.js 中安装这个插件:

// main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import { loggerPlugin } from './plugins/logger';
import { persistPlugin } from './plugins/persist';
import { uppercasePlugin } from './plugins/uppercase';

const app = createApp(App);
const pinia = createPinia();

pinia.use(loggerPlugin);
pinia.use(persistPlugin);
pinia.use(uppercasePlugin);

app.use(pinia);
app.mount('#app');

在组件中使用这个 store 并展示 uppercaseState

<template>
  <div>
    <p>Count: {{ counterStore.count }}</p>
    <p>Uppercase State: {{ counterStore.uppercaseState }}</p>
    <button @click="counterStore.increment">Increment</button>
    <button @click="counterStore.decrement">Decrement</button>
  </div>
</template>

<script>
import { useCounterStore } from '@/stores/counter';

export default {
  setup() {
    const counterStore = useCounterStore();
    return { counterStore };
  },
};
</script>

此时,uppercaseState 将展示 store 中所有字符串类型的 state 的大写版本。


网站公告

今日签到

点亮在社区的每一天
去签到