Il principale strumento esposto da Vue per il riutilizzo del codice e per astrarre funzionalità di basso livello, sono i componenti. Spesso però può capitare che sia necessario intervenire direttamente sul DOM della pagina tramite plugin esterni o per utilizzare API native del browser.
Per questi scopi, Vue mette a disposizione la possibilità di creare direttive personalizzate da richiamare all'interno dei nostri template esattamente come le direttive native di Vue (per esempio v-if
o v-model
).
Come per i mixin, anche le direttive personalizzate (o custom directives) possono essere applicate globalmente o localmente ad un particolare componente. Guardiamo subito un esempio esplicativo:
<div id="vue-app">
<div v-custom-background>Lorem Ipsum è un testo segnaposto utilizzato nel settore della tipografia e della stampa. Lorem Ipsum è considerato il testo segnaposto standard sin dal sedicesimo secolo, quando un anonimo tipografo prese una cassetta di caratteri e li assemblò per preparare un testo campione.</div>
<div v-custom-background="'#BBB'">Lorem Ipsum è un testo segnaposto utilizzato nel settore della tipografia e della stampa. Lorem Ipsum è considerato il testo segnaposto standard sin dal sedicesimo secolo, quando un anonimo tipografo prese una cassetta di caratteri e li assemblò per preparare un testo campione.</div>
</div>
Vue.directive('custom-background', {
inserted: function (el, binding) {
el.style.backgroundColor = binding.value || '#DDD';
}
});
var app = new Vue({
el: '#vue-app'
});
In questo esempio, abbiamo creato una direttiva personalizzata definita custom-background
, che permette di modificare direttamente tramite l'oggetto nativo style
il colore di sfondo di un nodo. Inoltre, tramite l'accesso a binding.value
possiamo offrire all'utilizzatore la possibilità di personalizzare il colore di sfondo. In questo caso, creare un componente non era la scelta ideale in quanto l'unico nostro scopo era agire su un aspetto nativo del DOM.
Da notare l'utilizzo sia dei doppi apici in quanto attributo HTML, sia di quelli singoli in quanto il valore dell'espressione deve essere una stringa. Per essere più personalizzabili, infatti, tutte le direttive ricevono un espressione e non una stringa, permettedo allo sviluppatore di sfruttare la reattività propria del framework.
Hook delle direttive personalizzate
Nell'esempio precedente abbiamo usato l'hook inserted
. Cerchiamo di capire perchè e quali altri hook vengono messi a disposizione da Vue per personalizzare le nostre direttive:
bind
viene invocato solamente una volta quando la direttiva viene associata al nodo;inserted
viene invocato quando il nodo è stato correttamente inserito all'interno del nodo padre;updated
viene invocato successivamente ad una modifica subita dal nodo;componentUpdated
viene invocato successivamente ad una modifica subita dai nodi figli del nodo decorato con la direttiva;unbind
viene invocato solamente una volta quando la direttiva viene disassociata dal nodo.
Considerando il fatto che spesso la direttiva più utilizzata è updated
, Vue presenta una modalità più short per utilizzare questo hook, dandolo per sottointeso:
Vue.directive('custom-directive', function (el, binding) {
//onUpdated
})
Paramentri e binding
Riferendosi sempre all'esempio di prima, abbiamo usato l'oggetto binding per recuperare il valore (se presente) inviato dall'utente tramite la property value
. Questo oggetto presenta però diverse altre opzioni:
value
rappresenta il valore dell'espressione passata come parametro;expression
rappresenta l'espressione passata come parametro (nell'esempio di prima avremmo avuto letteralmente '#BBB');name
rappresenta il nome della direttiva al netto del prefisso v-;arg
rappresenta l'eventuale attributo passato alla direttiva (nel caso dicustom-background.foo
, il valore diarg
sarebbefoo
);modifiers
rappresenta un oggetto contenente eventuali modificatori (nel caso dicustom-background.foo.bar
, il valore dimodifiers
sarebbe{ foo: true, bar: true }
);vnode
rappresenta il virtual node creato dal compilatore Vue;oldValue
rappresenta il valore dell'espressione precedente (solamente in caso di hookupdated
ecomponentUpdated
);oldNode
rappresenta il precedente virtual node (solamente in caso di hookupdated
ecomponentUpdated
).