Плагін - об'єкт з методом install(app, options) (або сама функція), який додає щось на рівні всього застосунку. Підключається через app.use():
// plugins/i18n.js
export default {
install(app, options) {
const translate = (key) =>
key.split('.').reduce((obj, part) => obj?.[part], options.messages) ?? key;
app.provide('i18n', { translate }); // для Composition API
app.config.globalProperties.$t = translate; // для шаблонів і Options API
app.directive('t', (el, binding) => (el.textContent = translate(binding.value)));
app.component('LocaleSwitcher', LocaleSwitcher);
},
};
// main.js
app.use(i18n, { messages: uk });
Що плагін може зареєструвати:
- глобальні компоненти (
app.component) і директиви (app.directive); - значення для
inject(app.provide) - сервіси, конфігурацію, клієнт API; - глобальні властивості (
app.config.globalProperties) - доступні в шаблонах як$t,$route; - глобальні обробники (
app.config.errorHandler), міксини (застарілий підхід).
Так влаштовані Vue Router (app.use(router)), Pinia, бібліотеки UI, i18n.
Як споживачам отримати доступ у <script setup>: не через globalProperties (вони доступні лише в шаблоні й this Options API), а через inject - найкраще обгорнути в composable:
export const I18nKey = Symbol('i18n');
export const useI18n = () => inject(I18nKey);
Символ як ключ - замість рядка, щоб плагіни не перезаписали значення одне одного. З TypeScript - InjectionKey<T> для типізації.
Типізація globalProperties - доповнення модуля:
declare module 'vue' {
interface ComponentCustomProperties {
$t: (key: string) => string;
}
}
Що варто враховувати:
- повторне
app.use()того самого плагіна Vue ігнорує; - SSR: застосунок створюється на кожен запит - плагін не повинен тримати стан на рівні модуля, інакше дані одного користувача «протечуть» до іншого. Стан - усередині
install(на екземпляр застосунку); - порядок має значення: плагін, що використовує роутер, підключається після роутера;
- глобальні компоненти й директиви з плагіна потрапляють у збірку повністю - для великих бібліотек краще імпорт окремих компонентів.