Pinia предоставляет мощный механизм расширения функциональности через
плагины, что позволяет добавлять общие функции, логирование, обработку
ошибок и асинхронные операции во все хранилища приложения. Плагин — это
функция, принимающая два аргумента: context и
store.
Сигнатура плагина:
function myPlugin(context) {
return (store) => {
// Расширение функционала хранилища
}
}
context содержит глобальные возможности Pinia, включая
метод pinia, доступ к другим хранилищам и опционально
app.store — конкретное хранилище, которое подключается к
плагину.Плагин подключается через метод use при создании
Pinia:
import { createPinia } from 'pinia';
const pinia = createPinia();
pinia.use(myPlugin);
Один из распространённых сценариев — добавление новых свойств или методов в каждый store. Это позволяет унифицировать логику, например, реализовать единое логирование изменений состояния.
function loggerPlugin() {
return (store) => {
store.$log = (msg) => {
console.log(`[${store.$id}] ${msg}`, store.$state);
};
};
}
pinia.use(loggerPlugin);
После подключения плагина любой store получает метод
$log:
const useUserStore = defineStore('user', {
state: () => ({ name: 'Alice' }),
});
const userStore = useUserStore();
userStore.$log('Store инициализирован');
Pinia позволяет обращаться к другим store внутри плагина через объект
pinia в контексте:
function crossStorePlugin(context) {
return (store) => {
const settingsStore = context.pinia._s.get('settings');
if (settingsStore) {
store.$settings = settingsStore;
}
};
}
Это особенно полезно при создании глобальных функций, зависящих от нескольких хранилищ, например, проверки авторизации на основе настроек приложения.
Pinia поддерживает реактивное слежение за состоянием store через
подписки ($subscribe). Плагин может автоматически
подключать логирование всех изменений:
function stateLoggerPlugin() {
return (store) => {
store.$subscribe((mutation, state) => {
console.log(`[Mutation] ${mutation.storeId}:`, mutation.events, state);
});
};
}
pinia.use(stateLoggerPlugin);
Такое решение позволяет централизованно отслеживать все изменения, не дублируя код в каждом store.
Плагины удобно использовать для интеграции с внешними API. Например, можно автоматически добавлять методы для загрузки данных:
function apiPlugin(context) {
return (store) => {
store.$fetchData = async (url) => {
try {
const response = await fetch(url);
const data = await response.json();
store.$state = { ...store.$state, ...data };
} catch (error) {
console.error(`[${store.$id}] Ошибка при загрузке:`, error);
}
};
};
}
В дальнейшем любой store сможет использовать $fetchData
без дублирования логики.
Плагины могут принимать параметры при подключении, что позволяет гибко настраивать их поведение:
function configurableLogger(options = { level: 'info' }) {
return (store) => {
store.$log = (msg) => {
if (options.level === 'debug') {
console.debug(`[${store.$id}] ${msg}`);
} else {
console.log(`[${store.$id}] ${msg}`);
}
};
};
}
pinia.use(configurableLogger({ level: 'debug' }));
При использовании TypeScript можно расширять типы store для корректной поддержки новых методов и свойств. Например:
import { PiniaPluginContext } from 'pinia';
function typedPlugin(context: PiniaPluginContext) {
return (store: any) => {
store.$log = (msg: string) => console.log(`[${store.$id}] ${msg}`);
};
}
declare module 'pinia' {
export interface PiniaCustomProperties {
$log(msg: string): void;
}
}
Это обеспечивает автодополнение и строгую проверку типов для всех новых функций, добавленных через плагины.
state напрямую без использования
реактивных методов Pinia.$subscribe и реактивные свойства для
слежения за состоянием вместо прямых мутаций.Плагины в Pinia позволяют создавать мощные, централизованные решения для повторного использования логики, упрощают поддержку и делают архитектуру приложения более масштабируемой.