Directives personnalisées

Introduction

En supplément de l’ensemble de directives fournies par défaut (v-model et v-show), Vue vous permet également d’enregistrer vos propres directives. Notez qu’avec Vue 2.0, les composants sont la forme principale de réutilisabilité et d’abstraction du code. Il y a cependant des cas où vous aurez juste besoin d’un accès de bas niveau aux éléments du DOM, et c’est là que les directives personnalisées vous seraient utiles. Un exemple pourrait être la prise du focus sur un élément de champ, comme celui-ci :

Quand la page se charge, cet élément prend le focus (notez que autofocus ne fonctionne pas sur Safari mobile). En fait, si vous n’avez cliqué sur rien du tout depuis votre arrivée sur la page, le champ ci-dessus devrait avoir le focus. À présent, jetons un œil à la directive qui pourrait accomplir cela :

// Enregistrer une directive globale appelée `v-focus`
Vue.directive('focus', {
  // Quand l'élément lié est inséré dans le DOM...
  inserted: function (el) {
    // L'élément prend le focus
    el.focus()
  }
})

Si vous préférez enregistrer à la place la directive en local, les composants acceptent également l’option directives :

directives: {
  focus: {
    // définition de la directive
    inserted: function (el) {
      el.focus()
    }
  }
}

Puis dans un template, vous pouvez utiliser le nouvel attribut v-focus sur n’importe quel élément, comme celui-ci :

<input v-focus>

Fonctions de hook

Un objet de définition de directive peut fournir plusieurs fonctions de hook (toutes optionnelles) :

Nous couvrerons VNodes plus en détail plus tard, quand nous discuterons des fonctions de rendu.

Nous allons explorer les arguments passés à ces hooks (c.-à-d. el, binding, vnode, et oldVnode) dans la prochaine section.

Arguments des hooks d’une directive

Les hooks d’une directive ont accès à ces arguments :

À l’exception de el, vous devez traiter ces arguments comme étant en lecture seule (« read-only ») et ne jamais les modifier. Si vous souhaitez partager des informations entre les hooks, il est recommandé de le faire à travers les attributs de données sur mesure de ses éléments (voir dataset).

Un exemple de directive personnalisée utilisant plusieurs de ces propriétés :

<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', {
  bind: function (el, binding, vnode) {
    var s = JSON.stringify
    el.innerHTML =
      'name: '       + s(binding.name) + '<br>' +
      'value: '      + s(binding.value) + '<br>' +
      'expression: ' + s(binding.expression) + '<br>' +
      'argument: '   + s(binding.arg) + '<br>' +
      'modifiers: '  + s(binding.modifiers) + '<br>' +
      'vnode keys: ' + Object.keys(vnode).join(', ')
  }
})

new Vue({
  el: '#hook-arguments-example',
  data: {
    message: 'bonjour !'
  }
})

Les arguments de directive peuvent être dynamiques. Par exemple, dans v-mydirective:argument=[dataproperty], argument est une valeur de chaine de caractère assignée à la propriété arg dans le paramètre de liaison (binding) du hook de directive et dataproperty est une référence à la propriété de donnée de l’instance de votre composant assignée à la valeur de propriété (value) pour le même paramètre de liaison (binding). Parce que les hooks de directive sont invoqués, la valeur de propriété (value) du paramètre de liaison (binding) va changer dynamiquement en se basant sur la valeur de dataproperty.

Un exemple de directive personnalisée utilisant un argument dynamique :

<div id="app">
  <p>Faite défiler la page vers le bas</p>
  <p v-tack:left="[dynamicleft]">Vous êtes maintenant décalé depuis le bord gauche au lieu du haut de page</p>
</div>
Vue.directive('tack', {
  bind(el, binding, vnode) {
    el.style.position = 'fixed';
    const s = (binding.arg == 'left' ? 'left' : 'top');
    el.style[s] = binding.value + 'px';
  }
})

// démarrer l'application
new Vue({
  el: '#app',
  data() {
    return {
      dynamicleft: 500
    }
  }
})

Fonction abrégée

Dans de nombreux cas, vous pourriez vouloir le même comportement pour les hooks bind et update, sans avoir besoin des autres hooks. Par exemple :

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

Objets littéraux

Si votre directive a besoin de plusieurs valeurs, vous pouvez également passer un objet JavaScript. Souvenez-vous, une directive peut accepter n’importe quelle expression JavaScript.

<div v-demo="{ color: 'white', text: 'bonjour !' }"></div>
Vue.directive('demo', function (el, binding) {
  console.log(binding.value.color) // => "white"
  console.log(binding.value.text)  // => "bonjour !"
})