
Ein Vue-3-Plugin ist ein Objekt mit einer Methode install(app, options), das du über app.use() installierst. Es registriert Komponenten und Direktiven, stellt Werte per app.provide() bereit und konfiguriert die Anwendung. Vue-2-Code auf Basis von Vue.prototype und Vue.mixin funktioniert nicht mehr.
Ein Vue-Plugin erweitert eine ganze Anwendung: eine überall verfügbare Komponente, eine Direktive, ein injizierbarer Wert, eine gemeinsame Konfiguration. Es ist der Mechanismus hinter Vue Router, Pinia und den meisten Bibliotheken des Ökosystems.
Was ein Plugin ist
Ein Objekt mit einer Methode install oder schlicht eine Funktion. Vue ruft sie mit der Anwendungsinstanz und den Optionen auf, die du an app.use() übergibst.
export default {
install(app, options) {
// hier passiert alles
}
}In Vue 2 bekam install den globalen Konstruktor Vue, und ein Plugin arbeitete mit Vue.prototype, Vue.mixin oder Vue.component. In Vue 3 gibt es keinen globalen Konstruktor mehr: install erhält die von createApp erzeugte Instanz, und alles läuft über sie. Ein unverändert kopiertes Vue-2-Plugin scheitert mit Cannot set properties of undefined (setting '$api') oder bricht stillschweigend ab.
Die Gegenüberstellung:
// Vue 3
Vue.use(Plugin) app.use(Plugin)
Vue.component('X', X) app.component('X', X)
Vue.directive('x', x) app.directive('x', x)
Vue.mixin({ … }) app.mixin({ … })
Vue.prototype.$api = api app.config.globalProperties.$api = api
app.provide('api', api) // besserEin vollständiges Plugin
Das folgende Plugin protokolliert das Mounten der Komponenten, stellt dieses Protokoll bereit und liefert eine Direktive mit. Es zeigt die vier Ansatzpunkte, die du kennen solltest.
export default {
install(app, options = {}) {
const prefixe = options.prefixe ?? '[monitor]'
const journal = []
// 1. globale Eigenschaft, in der Options API über this erreichbar
app.config.globalProperties.$journal = journal
// 2. Injection: der empfohlene Weg mit <script setup>
app.provide('journal', journal)
// 3. globale Direktive
app.directive('surligne', {
mounted(el, binding) {
el.style.backgroundColor = binding.value ?? '#fef08a'
}
})
// 4. globaler Mixin, läuft beim Mounten jeder Komponente
app.mixin({
mounted() {
journal.push(`${prefixe} ${this.$options.__name ?? 'anonyme'} monté`)
}
})
}
}Die Installation, mit oder ohne Optionen:
import { createApp } from 'vue'
import App from './App.vue'
import monitor from './plugins/monitor.js'
const app = createApp(App)
app.use(monitor, { prefixe: '[gekkode]' })
app.mount('#app')Ein zweimal installiertes Plugin wird nur einmal angewendet: Vue führt Buch über die Plugins, die bereits durch app.use() gelaufen sind.
provide statt globalProperties
app.config.globalProperties.$journal bildet die Vue-2-Gewohnheit this.$irgendwas nach. Das funktioniert, aber this gibt es in <script setup> nicht: Die Eigenschaft ist nur aus dem Template oder der Options API erreichbar. Autovervollständigung und Typisierung greifen dort ebenfalls nicht.
app.provide() ist der richtige Weg. Die Komponente holt sich den Wert über inject:
<script setup>
import { inject } from 'vue'
const journal = inject('journal')
</script>
<template>
<p>{{ journal.length }} composants montés</p>
</template>Damit sich Namen als Zeichenketten nicht ins Gehege kommen, exportierst du aus dem Plugin ein Symbol:
export const cleJournal = Symbol('journal')
export default {
install(app) {
app.provide(cleJournal, [])
}
}Komponenten ausliefern
Der häufigste Fall: eine Bibliothek von Komponenten ohne Import verfügbar machen.
import GkBouton from '../components/GkBouton.vue'
import GkCarte from '../components/GkCarte.vue'
export default {
install(app, { prefixe = 'Gk' } = {}) {
app.component(`${prefixe}Bouton`, GkBouton)
app.component(`${prefixe}Carte`, GkCarte)
}
}Achte auf den Preis dieser Bequemlichkeit: Eine global registrierte Komponente ist überall verfügbar, entzieht sich aber dem Tree Shaking. Sie landet auch dann im Bundle, wenn sie niemand benutzt. Registriere global nur, was wirklich allgegenwärtig ist.
Ein Plugin darf eine einfache Funktion sein
Wenn dir das Objekt mit der Methode install zu umständlich ist, genügt eine Funktion: Vue ruft sie mit denselben Argumenten auf.
export default function titrePlugin(app, options) {
app.config.globalProperties.$titre = options.titre
}Das veröffentlichungsfähige Paket
Probiere es zuerst in einem frischen Vite-Projekt aus. Für die Veröffentlichung auf npm exportierst du es als Default und lässt die Abhängigkeit auf Vue in den peerDependencies, damit das Hostprojekt seine eigene Kopie mitbringt:
{
"name": "gekkode-monitor",
"type": "module",
"main": "./dist/index.js",
"exports": { ".": "./dist/index.js" },
"peerDependencies": { "vue": "^3.5.0" }
}Vue-2-Plugins endeten oft mit if (window.Vue) window.Vue.use(Plugin), um sich selbst zu installieren, wenn die Seite Vue über ein script-Tag lud. In Vue 3 gibt es kein globales window.Vue mehr: Dieser Block ist nutzlos und gehört entfernt.
Der globale Mixin, als letztes Mittel
Das Beispiel-Plugin nutzt app.mixin, um jedes Mounten zu beobachten. Für ein querschnittliches Anliegen wie Telemetrie, bei dem du wirklich jede Komponente erwischen willst, ist das der richtige Griff.
Für alles andere nimmst du besser einen Composable: eine exportierte Funktion, die nur die interessierten Komponenten aufrufen. Ein globaler Mixin greift überall, auch dort, wo niemand damit rechnet, und macht die Herkunft eines Verhaltens schwer nachvollziehbar.
import { inject } from 'vue'
export function useJournal() {
const journal = inject('journal')
return {
journal,
ajouter: (message) => journal.push(message)
}
}Ein Plugin testen
Vue Test Utils nimmt Plugins samt Optionen in der Option global entgegen:
import { mount } from '@vue/test-utils'
import monitor from '@/plugins/monitor.js'
mount(MonComposant, {
global: { plugins: [[monitor, { prefixe: '[test]' }]] }
})Ohne Optionen reicht die Kurzform: plugins: [monitor].
Weiterlesen
Viele Bibliotheken des Ökosystems werden genau so installiert, von VueFire bis unhead für die Suchmaschinenoptimierung.
Plugins entfalten ihren Nutzen erst, wenn Komponenten und Injection sitzen. Sind dir diese Begriffe noch neu, nimm dir das Vue-3-Tutorial für Einsteiger vor, besonders die Kapitel zu Komponenten und Props. Für geteilten State ist Pinia selbst ein Plugin, und sein Quellcode lohnt die Lektüre.
Häufige Fehler
install bekommt die Anwendungsinstanz, nicht mehr den globalen Konstruktor. Vue.prototype gibt es nicht mehr: Nimm app.provide() oder app.config.globalProperties.this gibt es in <script setup> nicht: Die Eigenschaft ist nur im Template lesbar. Besser provide und inject.if (window.Vue) window.Vue.use(Plugin) findet in Vue 3 nichts mehr vor und gehört entfernt.

