Плагин — это способ добавить глобальную функциональность в Vue-приложение. Это может быть глобальный компонент, директива, метод, provide/inject значение или любая инициализационная логика.
Плагин — это объект с методом install или просто функция:
// Вариант 1: объект с install
const myPlugin = {
install(app, options) {
// app — экземпляр Vue приложения
// options — параметры, переданные при app.use(plugin, options)
// Добавить глобальный компонент
app.component('MyButton', MyButtonComponent)
// Добавить глобальную директиву
app.directive('focus', { mounted: (el) => el.focus() })
// Добавить глобальное свойство
app.config.globalProperties.$http = axios
// Provide для всего приложения
app.provide('i18n', createI18n(options.locale))
}
}
// Вариант 2: функция
const myPlugin = (app, options) => {
app.provide('config', options)
}import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Без опций
app.use(myPlugin)
// С опциями
app.use(i18nPlugin, { locale: 'ru' })
app.use(routerPlugin, { routes })
app.mount('#app')Важно: app.use() вызывает install один раз. Повторный вызов с тем же плагином игнорируется.
// plugins/notification.js
export const NotificationPlugin = {
install(app, options = {}) {
const { timeout = 3000, position = 'top-right' } = options
const notifications = ref([])
// Глобальный метод
app.config.globalProperties.$notify = (message, type = 'info') => {
const id = Date.now()
notifications.value.push({ id, message, type })
setTimeout(() => {
notifications.value = notifications.value.filter(n => n.id !== id)
}, timeout)
}
// Доступ через inject
app.provide('notifications', {
list: notifications,
add: app.config.globalProperties.$notify,
})
// Глобальный компонент
app.component('NotificationContainer', NotificationContainerComponent)
}
}// Использование в компоненте
const { $notify } = getCurrentInstance().proxy
$notify('Файл сохранён!', 'success')
// Или через inject
const { add } = inject('notifications')
add('Ошибка!', 'error')app.use(router)app.use(pinia)| Плагин | Composable |
|--------|-----------|
| Глобальная регистрация | Локальное использование |
| Регистрирует компоненты/директивы | Возвращает реактивное состояние |
| Один раз через app.use() | Вызывается в каждом компоненте |
| Для инфраструктуры (роутер, i18n) | Для логики (useForm, useFetch) |
Composable предпочтительнее для переиспользуемой логики. Плагин нужен когда требуется глобальная регистрация или доступ к экземпляру приложения.
Создание системы плагинов — реестр с install-функцией, аналог app.use() в Vue
// Реализуем механику Vue-плагинов:
// app.use() регистрирует плагин и вызывает install(app, options).
class VueApp {
constructor() {
this._installedPlugins = new Set()
this._components = {}
this._directives = {}
this._provides = {}
this.config = { globalProperties: {} }
}
// Аналог app.use()
use(plugin, options = {}) {
const installer = typeof plugin === 'function' ? plugin : plugin.install
// Защита от повторной установки
if (this._installedPlugins.has(plugin)) {
console.warn('[app.use] Плагин уже установлен, пропускаем')
return this
}
installer(this, options)
this._installedPlugins.add(plugin)
return this // для цепочки вызовов
}
// Аналог app.component()
component(name, comp) {
if (this._components[name]) {
console.warn(`[app] Компонент "${name}" уже зарегистрирован`)
}
this._components[name] = comp
console.log(`[app] Зарегистрирован компонент: ${name}`)
return this
}
// Аналог app.directive()
directive(name, def) {
this._directives[name] = def
console.log(`[app] Зарегистрирована директива: v-${name}`)
return this
}
// Аналог app.provide()
provide(key, value) {
this._provides[key] = value
console.log(`[app] Provide: "${String(key)}"`)
return this
}
// Получить inject (для тестирования)
inject(key) {
return this._provides[key]
}
info() {
console.log('\n=== Состояние приложения ===')
console.log('Компоненты:', Object.keys(this._components))
console.log('Директивы:', Object.keys(this._directives).map(d => 'v-' + d))
console.log('Provides:', Object.keys(this._provides))
console.log('Global props:', Object.keys(this.config.globalProperties))
console.log('Плагинов установлено:', this._installedPlugins.size)
}
}
// --- Создаём плагины ---
// Плагин как объект
const RouterPlugin = {
install(app, { routes = [], mode = 'history' } = {}) {
console.log(`[RouterPlugin] Инициализация (mode: ${mode}, маршрутов: ${routes.length})`)
const router = {
routes,
currentRoute: routes[0] || null,
push(path) { console.log('[Router] navigate to', path) },
replace(path) { console.log('[Router] replace to', path) },
}
app.provide('router', router)
app.config.globalProperties.$router = router
app.config.globalProperties.$route = router.currentRoute
app.component('RouterLink', { name: 'RouterLink' })
app.component('RouterView', { name: 'RouterView' })
}
}
// Плагин как функция
const i18nPlugin = (app, { locale = 'en', messages = {} } = {}) => {
console.log(`[i18nPlugin] Инициализация (locale: ${locale})`)
const i18n = {
locale,
messages,
t(key) {
return messages[locale]?.[key] ?? messages['en']?.[key] ?? key
},
}
app.provide('i18n', i18n)
app.config.globalProperties.$t = (key) => i18n.t(key)
}
// Плагин для уведомлений
const NotificationPlugin = {
install(app, { timeout = 3000 } = {}) {
console.log(`[NotificationPlugin] Инициализация (timeout: ${timeout}мс)`)
const queue = []
const notify = (msg, type = 'info') => {
const item = { id: Date.now(), msg, type }
queue.push(item)
console.log(` [notify] [${type.toUpperCase()}] ${msg}`)
return item.id
}
app.provide('notifications', { notify, queue })
app.config.globalProperties.$notify = notify
app.component('ToastContainer', { name: 'ToastContainer' })
}
}
// === Сборка приложения ===
console.log('=== Создаём Vue приложение ===\n')
const app = new VueApp()
app
.use(RouterPlugin, {
mode: 'history',
routes: [
{ path: '/', name: 'home' },
{ path: '/about', name: 'about' },
]
})
.use(i18nPlugin, {
locale: 'ru',
messages: {
ru: { hello: 'Привет', save: 'Сохранить' },
en: { hello: 'Hello', save: 'Save' },
}
})
.use(NotificationPlugin, { timeout: 5000 })
// Повторная установка — игнорируется
app.use(RouterPlugin)
app.info()
// Тестируем функциональность
console.log('\n=== Тест плагинов ===')
const i18n = app.inject('i18n')
console.log(i18n.t('hello')) // Привет
console.log(i18n.t('save')) // Сохранить
app.config.globalProperties.$notify('Данные сохранены!', 'success')
app.config.globalProperties.$router.push('/about')
console.log(app.config.globalProperties.$t('hello'))
Плагин — это способ добавить глобальную функциональность в Vue-приложение. Это может быть глобальный компонент, директива, метод, provide/inject значение или любая инициализационная логика.
Плагин — это объект с методом install или просто функция:
// Вариант 1: объект с install
const myPlugin = {
install(app, options) {
// app — экземпляр Vue приложения
// options — параметры, переданные при app.use(plugin, options)
// Добавить глобальный компонент
app.component('MyButton', MyButtonComponent)
// Добавить глобальную директиву
app.directive('focus', { mounted: (el) => el.focus() })
// Добавить глобальное свойство
app.config.globalProperties.$http = axios
// Provide для всего приложения
app.provide('i18n', createI18n(options.locale))
}
}
// Вариант 2: функция
const myPlugin = (app, options) => {
app.provide('config', options)
}import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Без опций
app.use(myPlugin)
// С опциями
app.use(i18nPlugin, { locale: 'ru' })
app.use(routerPlugin, { routes })
app.mount('#app')Важно: app.use() вызывает install один раз. Повторный вызов с тем же плагином игнорируется.
// plugins/notification.js
export const NotificationPlugin = {
install(app, options = {}) {
const { timeout = 3000, position = 'top-right' } = options
const notifications = ref([])
// Глобальный метод
app.config.globalProperties.$notify = (message, type = 'info') => {
const id = Date.now()
notifications.value.push({ id, message, type })
setTimeout(() => {
notifications.value = notifications.value.filter(n => n.id !== id)
}, timeout)
}
// Доступ через inject
app.provide('notifications', {
list: notifications,
add: app.config.globalProperties.$notify,
})
// Глобальный компонент
app.component('NotificationContainer', NotificationContainerComponent)
}
}// Использование в компоненте
const { $notify } = getCurrentInstance().proxy
$notify('Файл сохранён!', 'success')
// Или через inject
const { add } = inject('notifications')
add('Ошибка!', 'error')app.use(router)app.use(pinia)| Плагин | Composable |
|--------|-----------|
| Глобальная регистрация | Локальное использование |
| Регистрирует компоненты/директивы | Возвращает реактивное состояние |
| Один раз через app.use() | Вызывается в каждом компоненте |
| Для инфраструктуры (роутер, i18n) | Для логики (useForm, useFetch) |
Composable предпочтительнее для переиспользуемой логики. Плагин нужен когда требуется глобальная регистрация или доступ к экземпляру приложения.
Создание системы плагинов — реестр с install-функцией, аналог app.use() в Vue
// Реализуем механику Vue-плагинов:
// app.use() регистрирует плагин и вызывает install(app, options).
class VueApp {
constructor() {
this._installedPlugins = new Set()
this._components = {}
this._directives = {}
this._provides = {}
this.config = { globalProperties: {} }
}
// Аналог app.use()
use(plugin, options = {}) {
const installer = typeof plugin === 'function' ? plugin : plugin.install
// Защита от повторной установки
if (this._installedPlugins.has(plugin)) {
console.warn('[app.use] Плагин уже установлен, пропускаем')
return this
}
installer(this, options)
this._installedPlugins.add(plugin)
return this // для цепочки вызовов
}
// Аналог app.component()
component(name, comp) {
if (this._components[name]) {
console.warn(`[app] Компонент "${name}" уже зарегистрирован`)
}
this._components[name] = comp
console.log(`[app] Зарегистрирован компонент: ${name}`)
return this
}
// Аналог app.directive()
directive(name, def) {
this._directives[name] = def
console.log(`[app] Зарегистрирована директива: v-${name}`)
return this
}
// Аналог app.provide()
provide(key, value) {
this._provides[key] = value
console.log(`[app] Provide: "${String(key)}"`)
return this
}
// Получить inject (для тестирования)
inject(key) {
return this._provides[key]
}
info() {
console.log('\n=== Состояние приложения ===')
console.log('Компоненты:', Object.keys(this._components))
console.log('Директивы:', Object.keys(this._directives).map(d => 'v-' + d))
console.log('Provides:', Object.keys(this._provides))
console.log('Global props:', Object.keys(this.config.globalProperties))
console.log('Плагинов установлено:', this._installedPlugins.size)
}
}
// --- Создаём плагины ---
// Плагин как объект
const RouterPlugin = {
install(app, { routes = [], mode = 'history' } = {}) {
console.log(`[RouterPlugin] Инициализация (mode: ${mode}, маршрутов: ${routes.length})`)
const router = {
routes,
currentRoute: routes[0] || null,
push(path) { console.log('[Router] navigate to', path) },
replace(path) { console.log('[Router] replace to', path) },
}
app.provide('router', router)
app.config.globalProperties.$router = router
app.config.globalProperties.$route = router.currentRoute
app.component('RouterLink', { name: 'RouterLink' })
app.component('RouterView', { name: 'RouterView' })
}
}
// Плагин как функция
const i18nPlugin = (app, { locale = 'en', messages = {} } = {}) => {
console.log(`[i18nPlugin] Инициализация (locale: ${locale})`)
const i18n = {
locale,
messages,
t(key) {
return messages[locale]?.[key] ?? messages['en']?.[key] ?? key
},
}
app.provide('i18n', i18n)
app.config.globalProperties.$t = (key) => i18n.t(key)
}
// Плагин для уведомлений
const NotificationPlugin = {
install(app, { timeout = 3000 } = {}) {
console.log(`[NotificationPlugin] Инициализация (timeout: ${timeout}мс)`)
const queue = []
const notify = (msg, type = 'info') => {
const item = { id: Date.now(), msg, type }
queue.push(item)
console.log(` [notify] [${type.toUpperCase()}] ${msg}`)
return item.id
}
app.provide('notifications', { notify, queue })
app.config.globalProperties.$notify = notify
app.component('ToastContainer', { name: 'ToastContainer' })
}
}
// === Сборка приложения ===
console.log('=== Создаём Vue приложение ===\n')
const app = new VueApp()
app
.use(RouterPlugin, {
mode: 'history',
routes: [
{ path: '/', name: 'home' },
{ path: '/about', name: 'about' },
]
})
.use(i18nPlugin, {
locale: 'ru',
messages: {
ru: { hello: 'Привет', save: 'Сохранить' },
en: { hello: 'Hello', save: 'Save' },
}
})
.use(NotificationPlugin, { timeout: 5000 })
// Повторная установка — игнорируется
app.use(RouterPlugin)
app.info()
// Тестируем функциональность
console.log('\n=== Тест плагинов ===')
const i18n = app.inject('i18n')
console.log(i18n.t('hello')) // Привет
console.log(i18n.t('save')) // Сохранить
app.config.globalProperties.$notify('Данные сохранены!', 'success')
app.config.globalProperties.$router.push('/about')
console.log(app.config.globalProperties.$t('hello'))
Реализуй класс `PluginSystem` — упрощённую версию app.use() Vue. Метод `use(plugin, options)` принимает плагин (объект с install или функцию) и вызывает install(this, options). Повторный вызов с тем же плагином должен игнорироваться с предупреждением. Метод `provide(key, value)` сохраняет значение. Метод `inject(key)` возвращает сохранённое значение. Свойство `properties` — объект для глобальных свойств (аналог globalProperties). Метод `getInstalledCount()` возвращает количество установленных плагинов.
Для определения installer: const installer = typeof plugin === "function" ? plugin : plugin.install. Проверка повторной установки: if (this._installed.has(plugin)) { console.warn("..."); return this }. Затем installer(this, options) и this._installed.add(plugin). Для цепочки возвращай this из use() и provide().
Токены для AI-помощника закончились
Купи токены чтобы задавать вопросы AI прямо в уроке