Tous ceux qui connaissent Vue savent qu'une application Vue a un point d'entrée - le fichier 
main.js Là, en plus de créer une instance de Vue, il y a une importation et une sorte d'injection de dépendances de toutes vos dépendances globales (directives, composants, plugins). Plus le projet est volumineux, plus les dépendances deviennent importantes et, de plus, chacune a sa propre configuration. En conséquence, nous obtenons un énorme fichier avec toutes les configurations.
Cet article explique comment organiser les dépendances globales pour éviter cela.

Pourquoi l'écrire vous-même?
Beaucoup peuvent penser - pourquoi est-ce nécessaire s'il y a, par exemple, 
Nuxt , qui fera cela pour vous? Dans mes projets, je l'ai également utilisé, mais dans les projets simples, cela peut être redondant. De plus, personne n'a annulé des projets avec du code hérité qui vous tombent dessus comme de la neige sur la tête. Et connectez le cadre là-bas - faites-le pratiquement à partir de zéro.
Mastermind
L'organisateur d'une telle organisation était Nuxt. Il a été utilisé par moi sur un grand projet avec Vue.
Nuxt a une grande fonctionnalité - plugins. Chaque plugin est un fichier qui exporte une fonction. La configuration est transmise à la fonction, qui sera également transmise au constructeur Vue lors de la création de l'instance, ainsi qu'au 
magasin entier.
De plus, une fonctionnalité extrêmement utile, 
inject est disponible dans chaque plugin. Il effectue une injection de dépendance à l'instance racine de Vue et à l'objet de 
store . Et cela signifie que dans chaque composant, dans chaque fonction de stockage, la dépendance spécifiée sera disponible par 
this biais.
Où cela peut-il être utile?
En plus du fait que 
main.js "perd du poids" de 
main.js significative, vous aurez également la possibilité d'utiliser la dépendance n'importe où dans l'application sans importations inutiles.
Vue-router est un excellent exemple d'injection de dépendance. Il n'est pas utilisé très souvent - pour obtenir les paramètres de l'itinéraire actuel, pour faire une redirection, mais c'est une dépendance globale. S'il peut être utile dans n'importe quel composant, alors pourquoi ne pas le rendre mondial? De plus, grâce à cela, son état sera également stocké globalement et modifié pour l'ensemble de l'application.
Un autre exemple est la 
vue-wait . Les développeurs de ce plugin sont allés plus loin et ont ajouté la propriété 
$wait non seulement à l'instance Vue, mais aussi à la boutique vuex. Compte tenu des spécificités du plugin, cela s'avère extrêmement utile. Par exemple, le magasin a une action qui est appelée sur plusieurs composants. Et dans chaque cas, vous devez montrer le chargeur sur un élément. Au lieu d'appeler 
$wait.start('action') et 
$wait.end('action') avant et après chaque appel d'action, vous pouvez simplement appeler ces méthodes une fois dans l'action elle-même. Et c'est beaucoup plus lisible et moins verbeux que 
dispatch('wait/start', 'action' {root: true}) . Dans le cas du magasin, il s'agit de sucre syntaxique.
Des mots au code
La structure de base du projet
Voyons maintenant à quoi ressemble le projet:
src
- store
- App.vue
- main.js
main.js ressemble à ceci:
 import Vue from 'vue'; import App from './App.vue'; import store from './store'; new Vue({ render: h => h(App), store }).$mount('#app'); 
Nous connectons la première dépendance
Maintenant, nous voulons connecter 
axios à notre projet et créer une sorte de configuration pour celui-ci. J'ai suivi la terminologie Nuxt et créé un répertoire de 
plugins dans 
src . Le répertoire 
axios.js index.js et 
axios.js .
src
- plugins
-- index.js
-- axios.js
- store
- App.vue
- main.js
Comme mentionné ci-dessus, chaque plugin doit exporter une fonction. Dans le même temps, à l'intérieur de la fonction, nous voulons avoir accès au magasin et par la suite à la fonction d' 
inject .
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 = () => {};  
Comme vous pouvez le voir, le fichier 
index.js exporte également la fonction. Ceci est fait afin de pouvoir y passer l'objet 
app . Maintenant, 
main.js et appelons cette fonction.
main.js :
 import Vue from 'vue'; import App from './App.vue'; import store from './store'; import initPlugins from './plugins';  
Résultat
À ce stade, nous avons réalisé que nous avons supprimé la configuration du plugin de 
main.js dans un fichier séparé.
Soit dit en passant, l'avantage de transmettre l'objet d' 
app à tous nos plugins est qu'à l'intérieur de chaque plugin, nous avons maintenant accès au magasin. Vous pouvez l'utiliser librement en appelant 
commit , 
dispatch , ainsi qu'en accédant à 
store.state et 
store.getters .
Si vous aimez le style ES6, vous pouvez même le faire:
axios.js import axios from 'axios'; export default function ({store: {dispatch, commit, state, getters}}) { ... } 
Deuxième étape - Injection de dépendance
Nous avons déjà créé le premier plugin et maintenant notre projet ressemble à ceci:
src
- plugins
-- index.js
-- axios.js
- store
- App.vue
- main.js
Étant donné que dans la plupart des bibliothèques où cela est vraiment nécessaire, l'injection de dépendance est déjà implémentée à l'aide de 
Vue.use , nous allons créer notre propre plugin simple.
Par exemple, essayez de répéter ce que fait 
vue-wait . C'est une bibliothèque assez lourde, donc si vous voulez montrer le chargeur sur une paire de boutons, il vaut mieux l'abandonner. Cependant, je n'ai pas pu résister à sa commodité et répété dans son projet sa fonctionnalité de base, y compris le sucre syntaxique dans le magasin.
Plugin d'attente
Créez un autre fichier dans le répertoire des 
plugins - 
wait.jsJ'ai déjà un module vuex, que j'ai aussi appelé 
wait . Il fait trois étapes simples:
- 
start - définit la propriété state d'un objet nommé 
action sur 
true- 
end - supprime de l'état une propriété d'un objet nommé 
action- 
is - obtient de l'état une propriété d'un objet nommé 
actionDans ce plugin, nous allons l'utiliser.
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); } 
Et connectez notre 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); } 
Fonction d'injection
Maintenant, nous implémentons la fonction 
inject .
 
La magie de Vue.prototype
Maintenant sur la magie. La 
documentation Vue indique qu'il suffit d'écrire 
Vue.prototype.$appName = ' '; et 
$appName seront disponibles 
this .
Cependant, en réalité, il s'est avéré que ce n'est pas le cas. En raison de la recherche sur Google, il n'y avait aucune réponse pourquoi un tel design ne fonctionnait pas. J'ai donc décidé de contacter les auteurs du plugin qui l'ont déjà implémenté.
Mixin mondial
Comme dans notre exemple, j'ai regardé le code du plugin 
vue-wait . Ils offrent une telle implémentation (le code source est nettoyé pour plus de clarté):
 Vue.mixin({ beforeCreate() { const { wait, store } = this.$options; let instance = null; instance.init(Vue, store);  
Au lieu d'un prototype, il est proposé d'utiliser un mixin global. L'effet est fondamentalement le même, peut-être, à l'exception de certaines nuances. Mais étant donné que l'injection est effectuée dans le magasin ici, elle ne semble pas exactement dans le bon sens et ne correspond pas du tout à la documentation.
Et si c'était un prototype?
L'idée derrière la solution prototype utilisée dans le 
inject fonction d' 
inject été empruntée à Nuxt. Il semble beaucoup plus juste que le mixin mondial, alors je me suis installé.
  Vue.use(() => {  
Résultat
Après ces manipulations, nous avons l'opportunité d'y accéder 
this.$wait de n'importe quel composant, ainsi que de n'importe quelle méthode du magasin.
Qu'est-il arrivé?
Structure du projet:
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'); 
Conclusion
À la suite des manipulations, nous avons reçu une importation et un appel de fonction dans le fichier 
main.js Et maintenant, il est immédiatement clair où chercher la configuration pour chaque plugin et chaque dépendance globale.
Lors de l'ajout d'un nouveau plugin, il vous suffit de créer un fichier qui exporte la fonction, de l'importer dans 
index.js et d'appeler cette fonction.
Dans ma pratique, une telle structure s'est avérée très pratique, de plus, elle est facilement transférable d'un projet à l'autre. Maintenant, il n'y a plus de problème si vous devez faire l'injection de dépendances ou configurer un autre plugin.
Partagez votre expérience avec la gestion des dépendances dans les commentaires. Projets réussis!