Jeder, der mit Vue vertraut ist, weiß, dass eine Vue-Anwendung einen Einstiegspunkt hat - die Datei 
main.js Dort gibt es neben dem Erstellen einer Instanz von Vue einen Import und eine Art Abhängigkeitsinjektion aller Ihrer globalen Abhängigkeiten (Direktiven, Komponenten, Plugins). Je größer das Projekt, desto mehr Abhängigkeiten werden, die darüber hinaus jeweils ihre eigene Konfiguration haben. Als Ergebnis erhalten wir eine große Datei mit allen Konfigurationen.
In diesem Artikel wird erläutert, wie Sie globale Abhängigkeiten organisieren, um dies zu vermeiden.

Warum selbst schreiben?
Viele mögen denken - warum ist das notwendig, wenn es zum Beispiel 
Nuxt gibt , das dies für Sie 
erledigt ? In meinen Projekten habe ich es auch verwendet, aber in einfachen Projekten kann dies überflüssig sein. Darüber hinaus hat niemand Projekte mit Legacy-Code abgebrochen, die wie Schnee auf Ihrem Kopf auf Sie fallen. Und schließen Sie das Framework dort an - praktisch von Grund auf neu.
Mastermind
Der Organisator einer solchen Organisation war Nuxt. Es wurde von mir bei einem großen Projekt mit Vue verwendet.
Nuxt hat eine großartige Funktion - Plugins. Jedes Plugin ist eine Datei, die eine Funktion exportiert. Die Konfiguration wird an die Funktion übergeben, die beim Erstellen der Instanz auch an den Vue-Konstruktor sowie an den gesamten 
Speicher übergeben wird .
Darüber hinaus ist in jedem Plugin eine äußerst nützliche Funktion, 
inject verfügbar. Es wird eine Abhängigkeitsinjektion für die Stamminstanz von Vue und für das 
store . Dies bedeutet, dass in jeder Komponente, in jeder Speicherfunktion die angegebene Abhängigkeit dadurch verfügbar ist.
Wo kann das nützlich sein?
Zusätzlich zu der Tatsache, dass 
main.js erheblich „abnehmen“, erhalten Sie auch die Möglichkeit, die Abhängigkeit überall in der Anwendung ohne unnötige Importe zu verwenden.
Ein Paradebeispiel für Dependency Injection ist der 
Vue-Router . Es wird nicht sehr oft verwendet - um die Parameter der aktuellen Route abzurufen, um eine Umleitung durchzuführen, aber dies ist eine globale Abhängigkeit. Wenn es in einer Komponente nützlich sein kann, warum nicht global machen? Dank dessen wird der Status außerdem global gespeichert und für die gesamte Anwendung geändert.
Ein weiteres Beispiel ist 
vue-wait . Die Entwickler dieses Plugins gingen noch weiter und fügten die 
$wait Eigenschaft nicht nur der Vue-Instanz, sondern auch dem Vuex-Store hinzu. Angesichts der Besonderheiten des Plugins erweist sich dies als äußerst nützlich. Beispielsweise verfügt der Speicher über eine Aktion, die für mehrere Komponenten aufgerufen wird. In jedem Fall müssen Sie den Loader für ein Element anzeigen. Anstatt vor und nach jedem Aktionsaufruf 
$wait.start('action') und 
$wait.end('action') aufzurufen, können Sie diese Methoden einfach einmal in der Aktion selbst aufrufen. Und dies ist viel lesbarer und weniger ausführlich als der 
dispatch('wait/start', 'action' {root: true}) . Im Falle eines Geschäfts ist dies syntaktischer Zucker.
Von Wörtern zu Code
Die Grundstruktur des Projekts
Mal sehen, wie das Projekt jetzt aussieht:
src
- store
- App.vue
- main.js
main.js sieht 
main.js aus:
 import Vue from 'vue'; import App from './App.vue'; import store from './store'; new Vue({ render: h => h(App), store }).$mount('#app'); 
Wir verbinden die erste Abhängigkeit
Jetzt wollen wir 
Axios mit unserem Projekt verbinden und eine Konfiguration dafür erstellen. Ich folgte der Nuxt-Terminologie und erstellte ein 
plugins Verzeichnis in 
src . Im Verzeichnis befinden sich die 
axios.js index.js und 
axios.js .
src
- plugins
-- index.js
-- axios.js
- store
- App.vue
- main.js
Wie oben erwähnt, muss jedes Plugin eine Funktion exportieren. Gleichzeitig möchten wir innerhalb der Funktion Zugriff auf den Speicher und anschließend auf die 
inject Funktion haben.
axios.js import axios from 'axios'; export default function (app) {  
index.js :
 import Vue from 'vue'; import axios from './axios'; export default function (app) { let inject = () => {};  
Wie Sie sehen können, exportiert die Datei 
index.js auch die Funktion. Dies geschieht, um das 
app Objekt dort übergeben zu können. Lassen Sie uns nun 
main.js ändern und diese Funktion aufrufen.
main.js :
 import Vue from 'vue'; import App from './App.vue'; import store from './store'; import initPlugins from './plugins';  
Ergebnis
Zu diesem Zeitpunkt haben wir erreicht, dass wir die Plugin-Konfiguration aus 
main.js in einer separaten Datei entfernt haben.
Der Vorteil der Übergabe des 
app Objekts an alle unsere Plugins besteht übrigens darin, dass wir in jedem Plugin jetzt Zugriff auf den Store haben. Sie können es frei verwenden, indem Sie 
commit und 
dispatch aufrufen sowie auf 
store.state und 
store.getters .
Wenn Sie ES6-Stil mögen, können Sie dies sogar tun:
axios.js import axios from 'axios'; export default function ({store: {dispatch, commit, state, getters}}) { ... } 
Zweite Stufe - Abhängigkeitsinjektion
Wir haben bereits das erste Plugin erstellt und jetzt sieht unser Projekt so aus:
src
- plugins
-- index.js
-- axios.js
- store
- App.vue
- main.js
Da in den meisten Bibliotheken, in denen dies wirklich erforderlich ist, Dependency Injection bereits mit 
Vue.use implementiert ist, 
Vue.use wir unser eigenes einfaches Plugin.
Versuchen Sie beispielsweise zu wiederholen, was 
vue-wait tut. Dies ist eine ziemlich umfangreiche Bibliothek. Wenn Sie also den Loader auf zwei Schaltflächen anzeigen möchten, ist es besser, ihn zu verlassen. Ich konnte jedoch seiner Bequemlichkeit nicht widerstehen und wiederholte in seinem Projekt seine grundlegende Funktionalität, einschließlich des syntaktischen Zuckers im Laden.
Warten Sie Plugin
Erstellen Sie eine weitere Datei im 
plugins Verzeichnis - 
wait.jsIch habe bereits ein Vuex-Modul, das ich auch 
wait . Er macht drei einfache Schritte:
- 
start - setzt die state-Eigenschaft eines Objekts mit dem Namen 
action auf 
true- 
end - Entfernt eine Eigenschaft eines Objekts mit dem Namen 
action aus dem Status
- 
is - ruft vom Status eine Eigenschaft eines Objekts mit dem Namen 
actionIn diesem Plugin werden wir es verwenden.
wait.js export default function ({store: {dispatch, getters}}, inject) { const wait = { start: action => dispatch('wait/start', action), end: action => dispatch('wait/end', action), is: action => getters['wait/waiting'](action) }; inject('wait', wait); } 
Und verbinden Sie unser Plugin:
index.js :
 import Vue from 'vue'; import axios from './axios'; import wait from './wait'; export default function (app) { let inject = () => {}; Injection axios(app, inject); wait(app, inject); } 
Injizieren Sie die Funktion
Jetzt implementieren wir die 
inject Funktion.
 
Die Magie von Vue.prototype
Nun zur Magie. Die 
Vue-Dokumentation besagt, dass es ausreicht, 
Vue.prototype.$appName = ' '; zu schreiben 
Vue.prototype.$appName = ' '; und 
$appName werden hier verfügbar sein.
In Wirklichkeit stellte sich jedoch heraus, dass dies nicht der Fall ist. Aufgrund von Googeln gab es keine Antwort, warum ein solches Design nicht funktionierte. Daher habe ich mich entschlossen, die Autoren des Plugins zu kontaktieren, die dies bereits implementiert haben.
Globales Mixin
Wie in unserem Beispiel habe ich mir den 
vue-wait Plugin-Code angesehen. Sie bieten eine solche Implementierung an (der Quellcode wird aus Gründen der Übersichtlichkeit bereinigt):
 Vue.mixin({ beforeCreate() { const { wait, store } = this.$options; let instance = null; instance.init(Vue, store);  
Anstelle eines Prototyps wird vorgeschlagen, ein globales Mixin zu verwenden. Der Effekt ist vielleicht im Grunde der gleiche, vielleicht mit Ausnahme einiger Nuancen. Da die Injektion jedoch hier im Geschäft erfolgt, sieht sie nicht genau richtig aus und entspricht überhaupt nicht der Dokumentation.
Aber was ist, wenn Prototyp?
Die Idee hinter der im 
inject verwendeten Prototyplösung wurde von Nuxt übernommen. Es sieht viel richtiger aus als das globale Mixin, also habe ich mich darauf festgelegt.
  Vue.use(() => {  
Ergebnis
Nach diesen Manipulationen erhalten wir die Möglichkeit, darauf zuzugreifen 
this.$wait von jeder Komponente sowie von jeder Methode im Geschäft.
Was ist passiert?
Projektstruktur:
src
- plugins
-- index.js
-- axios.js
-- wait.js
- store
- App.vue
- main.js
index.js :
 import Vue from 'vue'; import axios from './axios'; import wait from './wait'; export default function (app) { let inject = (name, plugin) => { let key = `$${name}`; app[key] = plugin; app.store[key] = plugin; Vue.use(() => { if (Vue.prototype.hasOwnProperty(key)) { return; } Object.defineProperty(Vue.prototype, key, { get () { return this.$root.$options[key]; } }); }); }; axios(app, inject); wait(app, inject); } 
wait.js export default function ({store: {dispatch, getters}}, inject) { const wait = { start: action => dispatch('wait/start', action), end: action => dispatch('wait/end', action), is: action => getters['wait/waiting'](action) }; inject('wait', wait); } 
axios.js import axios from 'axios'; export default function (app) { axios.defaults.baseURL = process.env.API_BASE_URL; axios.defaults.headers.common['Accept'] = 'application/json'; axios.defaults.headers.post['Content-Type'] = 'application/json'; } 
main.js :
 import Vue from 'vue'; import App from './App.vue'; import store from './store'; import initPlugins from './plugins'; const app = { render: h => h(App), store }; initPlugins(app); new Vue(app).$mount('#app'); 
Fazit
Als Ergebnis der Manipulationen haben wir einen Import- und einen Funktionsaufruf in der Datei 
main.js . Und jetzt ist sofort klar, wo für jedes Plugin und jede globale Abhängigkeit nach der Konfiguration gesucht werden muss.
Wenn Sie ein neues Plugin hinzufügen, müssen Sie nur eine Datei erstellen, die die Funktion exportiert, in 
index.js und diese Funktion aufrufen.
In meiner Praxis hat sich eine solche Struktur als sehr praktisch erwiesen, außerdem kann sie leicht von Projekt zu Projekt übertragen werden. Jetzt gibt es keine Schmerzen mehr, wenn Sie Dependency Injection ausführen oder ein anderes Plugin konfigurieren müssen.
Teilen Sie Ihre Erfahrungen mit dem Abhängigkeitsmanagement in den Kommentaren mit. Erfolgreiche Projekte!