Pinia插件

Pinia插件

Pinia插件是一个函数,可以选择返回要添加到 store 的属性。它需要一个可选参数。一个context

export function myPiniaPlugin(context) {
    context.pinia // 使用`createPinia()`创建的pinia
    context.app // 使用`createApp()`创建的当前应用程序(仅限Vue3)
    context.store // 插件正在扩充的 store
    context.options // 定义春初的选项对象传递给`defineStore()`
    // ...
}

然后使用pinia.use()将此函数传递给pinia

pinia.use(myPiniaPlugin)

插件仅适用于在将pinia传递给应用程序后创建的 store,否则将不会被应用。

插件的作用

  • 向 Store 添加新属性
  • 定义 Store 时添加新选项
  • 为 Store 添加新方法
  • 包装现有方法
  • 更改甚至取消操作
  • 实现本地存储等副作用
  • 适用于特定 Store

向 Store 添加新属性

通过插件添加的属性会在所有 Store 中生效
这对于添加全局对象(如路由器、模式或 toast 管理器)

import { createPinia } from 'pinia'

// 为安装此插件后创建的每个store添加一个名为 `secret` 的属性
// 这可能在不同的文件中
function SecretPiniaPlugin() {
  return { secret: 'the cake is a lie' }
}

const pinia = createPinia()
// 将插件提供给 pinia
pinia.use(SecretPiniaPlugin)

// 在另一个文件中
const store = useStore()
store.secret // 'the cake is a lie'

定义 Store 时添加新选项

可以在定义 store 时创建新选项,以便以后从插件中使用它们。 例如,您可以创建一个 debounce 选项,允许您对任何操作进行去抖动:

defineStore('search', {
  actions: {
    searchContacts() {
      // ...
    },
  },

  // 稍后将由插件读取
  debounce: {
    // 将动作 searchContacts 防抖 300ms
    searchContacts: 300,
  },
})

然后插件可以读取该选项以包装操作并替换原始操作:

// 使用任何防抖库
import debounce from 'lodash/debunce'

pinia.use(({ options, store }) => {
  if (options.debounce) {
    // 我们正在用新的action覆盖这些action
    return Object.keys(options.debounce).reduce((debouncedActions, action) => {
      debouncedActions[action] = debounce(
        store[action],
        options.debounce[action]
      )
      return debouncedActions
    }, {})
  }
})

请注意,使用设置语法时,自定义选项作为第三个参数传递:

defineStore(
  'search',
  () => {
    // ...
  },
  {
    // 稍后将由插件读取
    debounce: {
      // 将动作 searchContacts 防抖 300ms
      searchContacts: 300,
    },
  }
)

添加新的外部属性

当添加外部属性、来自其他库的类实例或仅仅是非响应式的东西时,您应该在将对象传递给 pinia 之前使用markRaw()包装对象。 这是一个将路由添加到每个 store 的示例:

import { markRaw } from 'vue'
// 根据您的路由所在的位置进行调整
import { router } from './router'

pinia.use(({ store }) => {
  store.router = markRaw(router)
})

添加新状态

如果您想将新的状态属性添加到 store 或打算在 hydration 中使用的属性,您必须在两个地方添加它:

  • store 上,因此您可以使用 store.myState 访问它
  • store.$state 上,因此它可以在 devtools 中使用,并且在 SSR 期间被序列化。

请注意,这允许您共享 refcomputed 属性:

const globalSecret = ref('secret')
pinia.use(({ store }) => {
  // `secret` 在所有 store 之间共享
  store.$state.secret = globalSecret
  store.secret = globalSecret
  // 它会自动展开
  store.secret // 'secret'

  const hasError = ref(false)
  store.$state.hasError = hasError
  // 这个必须始终设置
  store.hasError = toRef(store.$state, 'hasError')

  // 在这种情况下,最好不要返回 `hasError`,因为它
  // 将显示在 devtools 的 `state` 部分
  // 无论如何,如果我们返回它,devtools 将显示它两次。
})

请注意,插件中发生的状态更改或添加(包括调用store.$patch())发生在存储处于活动状态之前,因此不会触发任何订阅

在插件中调用$subscribe

您也可以在插件中使用 store. s u b s c r i b e 和 s t o r e . subscribe 和 store. subscribestore.onAction :

pinia.use(({ store }) => {
  store.$subscribe(() => {
    // 在存储变化的时候执行
  })
  store.$onAction(() => {
    // 在 action 的时候执行
  })
})

实现本地存储等副作用

// pinia-plugin.js

// 导入 Pinia 和相应的模块
import { defineStorePlugin } from 'pinia';

// 定义插件
export const sessionStoragePlugin = defineStorePlugin({
  // 定义插件的名称
  name: 'sessionStoragePlugin',
  // 定义插件的安装方法
  install (store) {
    // 监听 Pinia 的更新
    store.$subscribe({
      // 监听数据的变化
      onStateChange(state) {
        // 将最新的数据保存到 sessionStorage
        sessionStorage.setItem(store.$id, JSON.stringify(state));
      },
      // 监听动作的触发
      // onAction(action) {
      //   // 在这里可以监听 Pinia 动作的触发
      // }
    });
  },
});

// main.js
import { createPinia } from 'pinia';
import { createApp } from 'vue';
import App from './App.vue';
import { sessionStoragePlugin } from './pinia-plugin'; // 导入插件

const pinia = createPinia();

// 安装插件
pinia.use(sessionStoragePlugin);
createApp(App).use(pinia).mount('#app');

适用于特定 Store

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋丶海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值