I mixin in Vue, come in qualsiasi altro linguaggio ad oggetti che li supporta, permettono di condividere parti di funzionalità tra i diversi componenti, evitando quindi la duplicazione del codice e facilitandone la manutenibilità e portabilità.
Quando un componente "usa" un mixin, le funzionalità comuni esposte da esso vengono di fatto "mixate" a quelle proprie del componente. Guardiamo subito un esempio:
<div id="vue-app">
<custom-button></custom-button>
<another-custom-button></another-custom-button>
</div>
var clickMixin = {
methods: {
onClick: function() {
alert('clicked');
}
}
}
Vue.component('custom-button', {
mixins: [clickMixin],
template: '<button @click="onClick">custom button</button>'
});
Vue.component('another-custom-button', {
mixins: [clickMixin],
template: '<button @click="onClick">another custom button</button>'
});
var app = new Vue({
el: '#vue-app'
});
In questo esempio, due componenti diversi (entrambi pulsanti), condividono la parte di logica per la gestione del click. Si nota subito che i mixins non sono un particolare oggetto Vue, ma vengono creati come normale mappa chiave-valore. Le chiavi dei mixins sono di fatto le stesse property che vengono passate durante la definizione di un componente Vue.
Strategie di merging
Abbiamo parlato di "mixare" le proprietà. Ma cosa vuol dire esattamente mixare? In base alla tipologia di property definita nel mixin, Vue adotta una particolare strategia di default, ottimizzata per il tipo di property:
- le hook functions (ad esempio
created
,mounted
odestroyed
), vengono concatenate in un unica funzione che invoca prima l'hook del mixin e successivamente quello del componente; - le property che accettano un oggetto (ad esempio
methods
,data
ocomponents
), vengono unificate in un unico oggetto, dando priorità in caso di collisione di nomi, alla proprietà del componente.
Nel caso queste regole standard non andassero bene, Vue espone la possibilità di definire delle strategie personalizzate di merging tramite un oggetto globale:
Vue.config.optionMergeStrategies.opzioneDaRidefinire = function (toVal, fromVal) {
// return mergedVal
}
Mixin globali
Come per i componenti, è possibile sia definire quali mixin usa un determinato componente, sia definire mixin globali, importati automaticamente da tutti i componenti dell'applicazione. Spesso questo approccio viene utilizzato per includere in tutti i componenti eventuali oggetti di configurazione, spesso ottenuti server-side e utilizzati appunto da ogni elemento dell'applicazione.
Per poter definire un mixin globale utilizziamo la sintassi Vue.mixin()
. Ecco l'esempio di prima riscritto:
Vue.mixin({
methods: {
onClick: function() {
alert('clicked');
}
}
});
Vue.component('custom-button', {
template: '<button @click="onClick">custom button</button>'
});
Vue.component('another-custom-button', {
template: '<button @click="onClick">another custom button</button>'
});
var app = new Vue({
el: '#vue-app'
});
Gli stessi sviluppatori di Vue suggeriscono di non abusare di questo approccio, dato che può portare sia ad un appesantimento dell'applicazione poiché i componenti diventano di fatto più pesanti, sia ad un peggioramento della qualità e della leggibilità del codice.