跳到主要内容

Plugins

pinia.use(myPiniaPlugin)

This is useful to add global objects like the router, modal, or toast managers

Introduction

A Pinia plugin is a function that optionally returns properties to be added to a store. It takes one optional argument, a context

export function myPiniaPlugin(context) {
context.pinia // the pinia created with `createPinia()`
context.app // the current app created with `createApp()` (Vue 3 only)
context.store // the store the plugin is augmenting
context.options // the options object defining the store passed to `defineStore()`
// ...
}

Augmenting a Store

Note that every store is wrapped with reactive, automatically unwrapping any Ref (ref(), computed(), ...) it contains

This is why you can access all computed properties without .value and why they are reactive.

const sharedRef = ref('shared')
pinia.use(({ store }) => {
// each store has its individual `hello` property
store.hello = ref('secret')
// it gets automatically unwrapped
store.hello // 'secret'

// all stores are sharing the value `shared` property
store.shared = sharedRef
store.shared // 'shared'
})

Adding new external properties

When adding external properties, class instances that come from other libraries, or simply things that are not reactive, you should wrap the object with markRaw() before passing it to pinia

import { markRaw } from 'vue'
// adapt this based on where your router is
import { router } from './router'

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

Adding new options

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

// this will be read by a plugin later on
debounce: {
// debounce the action searchContacts by 300ms
searchContacts: 300,
},
})
// use any debounce library
import debounce from 'lodash/debounce'

pinia.use(({ options, store }) => {
if (options.debounce) {
// we are overriding the actions with new ones
return Object.keys(options.debounce).reduce((debouncedActions, action) => {
debouncedActions[action] = debounce(
store[action],
options.debounce[action]
)
return debouncedActions
}, {})
}
})

Note that custom options are passed as the 3rd argument when using the setup syntax

defineStore(
'search',
() => {
// ...
},
{
// this will be read by a plugin later on
debounce: {
// debounce the action searchContacts by 300ms
searchContacts: 300,
},
}
)

TypeScript

Typing plugins

import { PiniaPluginContext } from 'pinia'

export function myPiniaPlugin(context: PiniaPluginContext) {
// ...
}

Typing new store properties

When adding new properties to stores, you should also extend the PiniaCustomProperties interface

import 'pinia'
import type { Router } from 'vue-router'

declare module 'pinia' {
export interface PiniaCustomProperties {
// by using a setter we can allow both strings and refs
set hello(value: string | Ref<string>)
get hello(): string

// you can define simpler values too
simpleNumber: number

// type the router added by the plugin above (#adding-new-external-properties)
router: Router
}
}

Typing new creation options

import 'pinia'

declare module 'pinia' {
export interface DefineStoreOptionsBase<S, Store> {
// allow defining a number of ms for any of the actions
debounce?: Partial<Record<keyof StoreActions<Store>, number>>
}
}