
Vue mixins adalah cara yang disarankan untuk berbagi fungsionalitas umum antar komponen. Mereka baik-baik saja sampai Anda menggunakan lebih dari satu untuk mereka. Itu karena mereka tersirat oleh desain dan mencemari konteks komponen Anda. Mari kita coba perbaiki ini dengan memberi mereka sebanyak mungkin kesaksian.
Tujuan
Kami ingin memiliki mixin global yang memberikan komponen apa pun yang disebut prop types
dan output array kelas CSS yang disebut mods
yang berasal dari baseClass
.
Diberikan markup ini:
<SampleComponent :types="['active', 'block']"></SampleComponent>
Kami berharap memiliki ini (dengan asumsi baseClass
kami adalah sample-component
):
<div class="sample-component sample-component--active sample-component--block"></div>
Pendekatan naif
Dari hanya membaca dokumentasi Vue, pemikiran pertama Anda mungkin hanya menggunakan penggabungan properti bawaan dan menyediakan mods
sebagai properti yang dikomputasi dalam komponen yang diinginkan.
// SampleComponent.vue <template> <div class="sample-component" :class="mods"><slot /></div> </template>
import bemMods from 'bemMods.js'; export default { name: 'SampleComponent', mixins: [ bemMods('sample-component') ] }
Pendekatan ini menderita banyak masalah:
- Kode Boilerplate di setiap komponen. (setidaknya dalam pendekatan Vue)
- Ketergantungan pada argumen
baseClass
. - Tidak ada indikasi yang jelas dari mana properti
mods
berasal. - Konflik nama mudah dilakukan.
Kami akan mencoba memperbaiki semua masalah ini di langkah berikutnya.
Mixin dengan ekspor eksplisit
Vue memiliki mekanisme Injeksi Ketergantungan, yang disebut Inject \ Provid . Ini berpotensi memecahkan masalah kita dengan konteks polusi.
Pada awalnya, mari kita beralih dari mixin sederhana ke sebuah plugin, yang menerima opsi, yang akan kita gunakan nanti untuk menghindari konflik nama.
Kedua, kita juga bisa menggunakan kembali nama komponen kita sebagai baseClass
dan tidak memasukkan itu sebagai opsi khusus di setiap komponen tunggal.
Dan terakhir kita akan meninggalkan opsi untuk melewatkan baseClass
sebagai argumen fungsi jika baseClass
komponen kita tidak cocok dengan namanya.
Kami sekarang siap untuk mendaftarkan plugin kami secara global.
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods);
Kami juga dapat menyesuaikan bagaimana alat peraga kami dipanggil, dengan menyediakan objek opsi.
import Vue from 'vue'; import bemMods from 'bemMods.js'; Vue.use(bemMods, { propName: 'modifiers', modsName: 'classes' });
Dan inilah tampilan komponen kami setelah refactoring mixin:
<template> <div class="sample-component" :class="mods"><slot /></div> </template>
export default { name: 'SampleComponent',
Mari kita bayangkan komponen kita tidak memiliki name
atau memiliki baseClass
berbeda dari namanya:
<template> <div class="special-component" :class="mods('snowflake')"><slot /></div> </template>
export default { name: 'SpecialComponent', inject: ['mods'] }
Atau jika kita ingin siap untuk penghapusan refactoring atau plugin:
export default { name: 'SomeComponent', inject: {
Anda juga dapat menggunakan Symbol
sebagai nama mod untuk sepenuhnya menghilangkan konflik nama, tetapi itu mengharuskan Anda untuk memasukkan simbol itu di setiap komponen tunggal di mana Anda ingin menggunakan bemMods
.
Kami tidak secara implisit menentukan nama prop kami, tetapi itu adalah batasan mixin inti, yang kami coba atasi dengan nama prop kustom di konfigurasi plugin.
Semoga ini bisa membantu Anda dan Anda telah menemukan cara menulis mixin yang lebih baik untuk Vue.