Semua orang yang mengenal Vue tahu bahwa aplikasi Vue memiliki satu titik masuk - file 
main.js Di sana, selain membuat instance Vue, ada impor dan semacam Injeksi Ketergantungan dari semua dependensi global Anda (arahan, komponen, plugin). Semakin besar proyek, semakin banyak ketergantungan menjadi, yang, apalagi, masing-masing memiliki konfigurasi sendiri. Hasilnya, kami mendapatkan satu file besar dengan semua konfigurasi.
Artikel ini akan membahas cara mengatur dependensi global untuk menghindari hal ini.

Mengapa menulisnya sendiri?
Banyak yang mungkin berpikir - mengapa ini perlu jika ada, misalnya, 
Nuxt , yang akan melakukan ini untuk Anda? Dalam proyek saya, saya juga menggunakannya, tetapi dalam proyek sederhana ini mungkin berlebihan. Selain itu, tidak ada yang membatalkan proyek dengan kode lawas yang jatuh pada Anda seperti salju di kepala Anda. Dan hubungkan kerangka kerja di sana - praktis melakukannya dari awal.
Dalang
Penyelenggara organisasi semacam itu adalah Nuxt. Itu digunakan oleh saya pada proyek besar dengan Vue.
Nuxt memiliki fitur hebat - plugin. Setiap plugin adalah file yang mengekspor suatu fungsi. Konfigurasi dilewatkan ke fungsi, yang juga akan diteruskan ke konstruktor Vue saat membuat instance, serta seluruh 
toko .
Selain itu, fitur yang sangat berguna, 
inject tersedia di setiap plugin. Itu membuat Dependency Injection ke instance root dari Vue dan ke objek 
store . Dan ini berarti bahwa dalam setiap komponen, dalam setiap fungsi penyimpanan, ketergantungan yang ditentukan akan tersedia melalui 
this .
Di mana ini bisa berguna?
Selain fakta bahwa 
main.js secara signifikan menurunkan berat badan, Anda juga akan mendapatkan kesempatan untuk menggunakan dependensi di mana saja dalam aplikasi tanpa impor yang tidak perlu.
Contoh utama dari Dependency Injection adalah 
vue-router . Ini tidak sering digunakan - untuk mendapatkan parameter dari rute saat ini, untuk membuat arahan ulang, tetapi ini adalah ketergantungan global. Jika itu bisa berguna dalam komponen apa pun, lalu mengapa tidak membuatnya global? Selain itu, berkat ini, kondisinya juga akan disimpan secara global dan diubah untuk seluruh aplikasi.
Contoh lain adalah 
vue-wait . Pengembang plugin ini melangkah lebih jauh dan menambahkan properti 
$wait tidak hanya ke instance Vue, tetapi juga ke toko vuex. Mengingat spesifikasi plugin yang spesifik, ini terbukti sangat berguna. Misalnya, toko memiliki tindakan yang disebut pada beberapa komponen. Dan dalam setiap kasus, Anda perlu menunjukkan loader pada beberapa elemen. Alih-alih memanggil 
$wait.start('action') dan 
$wait.end('action') sebelum dan setelah setiap panggilan aksi, Anda dapat memanggil metode ini sekali saja dalam aksi itu sendiri. Dan ini jauh lebih mudah dibaca dan lebih sedikit verbose daripada 
dispatch('wait/start', 'action' {root: true}) . Dalam hal toko, ini adalah gula sintaksis.
Dari kata ke kode
Struktur dasar proyek
Mari kita lihat seperti apa proyek itu sekarang:
src
- store
- App.vue
- main.js
main.js terlihat seperti ini:
 import Vue from 'vue'; import App from './App.vue'; import store from './store'; new Vue({ render: h => h(App), store }).$mount('#app'); 
Kami menghubungkan ketergantungan pertama
Sekarang kami ingin menghubungkan 
aksioma ke proyek kami dan membuat semacam konfigurasi untuknya. Saya mengikuti terminologi Nuxt dan membuat direktori 
plugins di 
src . Di dalam direktori terdapat 
axios.js index.js dan 
axios.js .
src
- plugins
-- index.js
-- axios.js
- store
- App.vue
- main.js
Seperti disebutkan di atas, setiap plugin harus mengekspor fungsi. Pada saat yang sama, di dalam fungsi kami ingin memiliki akses ke toko dan fungsi 
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 = () => {};  
Seperti yang Anda lihat, file 
index.js juga mengekspor fungsi. Ini dilakukan agar dapat melewati objek 
app sana. Sekarang mari kita ubah 
main.js dan panggil fungsi ini.
main.js :
 import Vue from 'vue'; import App from './App.vue'; import store from './store'; import initPlugins from './plugins';  
Hasil
Pada tahap ini, kami telah mencapai bahwa kami menghapus konfigurasi plugin dari 
main.js dalam file terpisah.
Ngomong-ngomong, manfaat dari melewatkan objek 
app ke semua plugin kita adalah bahwa di dalam setiap plugin kita sekarang memiliki akses ke toko. Anda dapat menggunakannya dengan bebas dengan memanggil 
commit , 
dispatch , serta mengakses 
store.state dan 
store.getters .
Jika Anda menyukai gaya ES6, Anda bahkan dapat melakukan ini:
axios.js import axios from 'axios'; export default function ({store: {dispatch, commit, state, getters}}) { ... } 
Tahap Kedua - Injeksi Ketergantungan
Kami telah membuat plugin pertama dan sekarang proyek kami terlihat seperti ini:
src
- plugins
-- index.js
-- axios.js
- store
- App.vue
- main.js
Karena di sebagian besar perpustakaan di mana itu benar-benar diperlukan, Dependency Injection sudah diterapkan menggunakan 
Vue.use , kita akan membuat plugin sederhana kita sendiri.
Misalnya, coba ulangi apa yang 
vue-wait lakukan. Ini adalah perpustakaan yang agak berat, jadi jika Anda ingin menunjukkan loader pada sepasang tombol, lebih baik untuk meninggalkannya. Namun, saya tidak dapat menahan kenyamanannya dan mengulangi dalam proyeknya fungsi dasarnya, termasuk gula sintaksis di toko.
Tunggu plugin
Buat file lain di direktori 
plugins - 
wait.jsSaya sudah memiliki modul vuex, yang juga saya sebut 
wait . Dia melakukan tiga langkah sederhana:
- 
start - set properti state dari objek bernama 
action menjadi 
true- 
end - menghapus dari properti properti dari suatu 
action bernama 
action- 
is - get from state properti dari objek bernama 
actionDalam plugin ini kita akan menggunakannya.
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); } 
Dan hubungkan plugin kami:
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); } 
Fungsi injeksi
Sekarang kami menerapkan fungsi 
inject .
 
Keajaiban Vue.prototype
Sekarang tentang sihir. 
Dokumentasi Vue mengatakan cukup untuk menulis 
Vue.prototype.$appName = ' '; dan 
$appName akan tersedia untuk 
this .
Namun, pada kenyataannya ternyata tidak demikian. Karena googling, tidak ada jawaban mengapa desain seperti itu tidak berhasil. Oleh karena itu, saya memutuskan untuk menghubungi penulis plugin yang sudah menerapkan ini.
Mixin global
Seperti dalam contoh kita, saya melihat kode plugin 
vue-wait . Mereka menawarkan implementasi seperti itu (kode sumber dibersihkan untuk kejelasan):
 Vue.mixin({ beforeCreate() { const { wait, store } = this.$options; let instance = null; instance.init(Vue, store);  
Alih-alih prototipe, diusulkan untuk menggunakan mixin global. Efeknya pada dasarnya sama, mungkin, dengan pengecualian beberapa nuansa. Tetapi mengingat injeksi dilakukan di toko di sini, itu tidak terlihat persis dengan cara yang benar dan sama sekali tidak sesuai dengan dokumentasi.
Tapi bagaimana kalau prototipe?
Gagasan di balik solusi prototipe yang digunakan dalam 
inject fungsi 
inject dipinjam dari Nuxt. Kelihatannya jauh lebih benar daripada mixin global, jadi saya memutuskannya.
  Vue.use(() => {  
Hasil
Setelah manipulasi ini, kami mendapat kesempatan untuk mengaksesnya 
this.$wait dari komponen apa pun, serta metode apa pun di toko.
Apa yang terjadi
Struktur proyek:
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'); 
Kesimpulan
Sebagai hasil dari manipulasi kami menerima satu impor dan satu panggilan fungsi di file 
main.js Dan sekarang sudah jelas tempat untuk mencari konfigurasi untuk setiap plugin dan setiap ketergantungan global.
Saat menambahkan plugin baru, Anda hanya perlu membuat file yang mengekspor fungsi, impor ke 
index.js dan panggil fungsi ini.
Dalam praktik saya, struktur seperti itu telah terbukti sangat nyaman, apalagi, mudah ditransfer dari proyek ke proyek. Sekarang tidak ada rasa sakit jika Anda perlu melakukan Dependency Injection atau mengkonfigurasi plugin lain.
Bagikan pengalaman Anda dengan manajemen ketergantungan di komentar. Proyek yang berhasil!