Mini-cours sur vue.js

Les directives

Une directive est un attribut "spécial" d'une balise HTML. Il est "spécial" car non conforme au HTML5 (d'où l'apparition d'erreurs lors d'un test de validation du fichier HTML)

Le nom d'une directive commence par v-. Après son nom suit le signe =, suit une chaîne de caractères entourée de guillemets qui est interprété comme du JavaScript. Cette chaîne de caractères est un nom de variable, de fonction ou une expression JS évaluable.

Classement des 13 directives
Interpolation Rendu conditionnel Rendu de liste Événement Liaison
v-text v-show v-for v-on:event v-bind:attr_HTML
v-html v-if v-model
v-pre v-else-if
v-once v-else
v-cloak

v-slot

v-if, v-else-if et v-else

Syntaxe : v-if="expression". L'expression est évaluée à faux si l'évaluation vaut : false, 0, "", null, undefined, NaN

Bonjour

Bonsoir

n < 10

n >=10 et n< 20

n >= 20

Code HTML

<div id="app_if">

  <p v-if="isAvant18h">Bonjour</p>
  <p v-else>Bonsoir</p>

  <p v-if="n < 10">n < 10</p>
  <p v-else-if="n >= 10 && n < 20"> n >=10 et n< 20</p>
  <p v-else>n >= 20</p>

</div>

La balise HTML contenant la directive v-else doit suivre immédiatement celle contenant la directive v-if ou v-else-if. Cette directive n'attend aucune valeur (donc v-else="" = v-else="qqch" = v-else)

La balise HTML contenant la directive v-else-if doit suivre immédiatement celle contenant la directive v-if ou un autre v-else-if. (Ainsi, la directive v-else-if est située entre la directive v-if et la directive v-else)

Syntaxe : v-else-if="expression". L'expression est évaluée à faux si l'évaluation vaut : false, 0, "", null, undefined, NaN

Code JS

var app_if = new Vue({
  el: '#app_if',
  data: {
    isAvant18h:false,
    n:6
  }
});

v-else

Voir aussi : v-if (guide)

v-on:event = @event

Le constructeur de la class Vue reçoit un objet qui peut contenir un couple dont la clé est nommée methods. La valeur de cette clé est un objet JS. Cet objet JS contient toutes les fonctions de l'application.

Syntaxe :

nom de méthode :
<button v-on:click="faireCeci"></button>

évènement dynamique (2.6.0+) :
<button v-on:[event]="doThis"></button>

ligne d'instruction :
<button v-on:click="faireCela('hello', $event)"></button>

notation abrégée :
<button @click="faireCeci"></button>

notation abrégée d'un évènement dynamique (2.6.0+) :
<button @[event]="doThis"></button>

stoppe la propagation :
<button @click.stop="faireCeci"></button>

empêche le comportement par défaut :
<button @click.prevent="faireCeci"></button>

empêche le comportement par défaut sans expression :
<form @submit.prevent></form>

enchainer les modificateurs :
<button @click.stop.prevent="faireCeci"></button>

modificateur de touche avec un keyAlias :
<input @keyup.enter="onEnter">

modificateur de touche avec un keyCode :
<input @keyup.13="onEnter">

l'évènement click sera déclenché une seule fois maximum :
<button v-on:click.once="faireCeci"></button>

syntaxe objet (2.4.0+) :
<button v-on="{ mousedown: faireCeci, mouseup: faireCela }"></button>

{{ message }}

⚠ L'attribut @nom_événement="..." peut être supprimé lors d'un nettoyage du code via l'outil Tidy.

Code HTML (avec un nom de fonction)

<div id="app_on">
  <p>{{ message }}</p>
  <p><button v-on:click="reverseMessage">Retourner le texte ci-dessus</button></p>
</div>

Code JS

var app_on = new Vue({
  el: '#app_on',
  data: {
    message: 'Thibaut'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})

this représente l'objet JS (ici, app_on).
Rappel : reverseMessage: function (){...} peut s'écrire reverseMessage(){...}


{{ nb }}

Code HTML (avec une expression)

<div id="app_on2">
  <button @click="nb++">Incrémenter</button> {{ nb }}
</div>

Code JS

var app_on2 = new Vue({
  el: '#app_on2',
  data: {
    nb: 0
  }
})

Les modificateurs

Modificateurs génériques

Modificateurs liés à la souris

Modificateurs liés au clavier (keyAlias)

Ces modificateurs sont utilisés pour déclencher l'événement seulement lorsque la touche correspondante est pressée.

Ces modificateurs correspondent aux touches les plus fréquemment utilisées dans la gestion d'événements.

Il est également possible de lier une touche à une fonction, via son KeyCode. Toutefois,  l'utilisation des évènements keyCode est déprécié et pourrait ne plus être supportée dans de futurs navigateurs. 

Modificateurs liés aux touches-système

        Va aussi émettre un évènement si les touches Alt et Shift sont pressées :
<button v-on:click.ctrl="onClick">A</button>

Va émettre un évènement seulement si la touche Ctrl est pressée sans aucune autre touche :
<button v-on:click.ctrl.exact="onCtrlClick">A</button>

Va émettre un évènement si aucune touche n'est pressée :
<button v-on:click.exact="onClick">A</button>

v-on (référence)

Pour plus d'info : sur v-on (guide)

v-show

La directive v-show permet d'afficher ou cacher le contenu de la balise dans laquelle elle est incluse. La valeur de cette directive est un booléen, une variable booléenne ou un nombre entier. Dans ce dernier cas, s'il vaut 0 => false, et true dans les autres cas.

Texte visible

Syntaxe : v-show=" true | false | n | nom_variable/fonction_booléenne"

Code HTML

<div id="app_show">
  <p v-show="isVisible">Texte visible</p>
  <p><button  v-on:click="changeEtat">Changer la visibilité</button></p>
</div>

Code JS

var app_show = new Vue({
  el: '#app_show',
  data: {
    isVisible: 2
  },
  methods: {
    changeEtat : function(){
     this.isVisible = (this.isVisible) ? false : true;
    }
  }
});

La directive v-show permet de basculer (toggle) la visibilité d'un élément en CSS (display). C'est plus performant que v-if, où tout l'élément HTML est détruit et recréé à chaque affichage et chaque destruction. L'état de visibilité est souvent lié à une variable (data:) ou une fonction (methods:).

Cette directive est plus performante que v-if. Toutefois, elle ne peut être utilisée dans un template (d'un composant). Il faut aller utiliser la directive v-if.

Mauvais code :

<div v-if="afficher"> ... </div>
<div v-else=""> ... </div>

Bon code  :

<div show="afficher"> ... </div>
<div show="!afficher"> ... </div>

v-show

v-pre

La directive v-pre n'attend aucune valeur. Elle rend le contenu de la balise statique (et donc aussi les balises enfants). Ainsi, au sein de l'application, il est possible d'afficher les doubles accolades, ouvrantes et fermantes, sans que leur contenu puisse être remplacé.

{{ msg }} => msg n'est pas remplacé par le contenu d'une variable, fonction, ...

Code HTML

<div id="app_pre">
  <p v-pre>{{ msg }} => msg n'est pas remplacé par le contenu d'une variable, fonction, ...</p>
</div>

L'outil Tidy peut donner une valeur vide (="") aux attributs qui n'en ont pas. Ainsi, pre sera remplacé par pre=""

Code JS

var app_pre = new Vue({
  el: '#app_pre',
  data: {
    msg: 'Mon texte'
  }
});

v-pre

v-for

La directive v-for permet de répéter des balises HTML (dans la mémoire du navigateur) sur base d'un tableau de données.

Syntaxe = alias in expressionalias est l'élément courant du type de l'expression qui peut être du type : Array | Object | number | string | Iterable (depuis 2.6)

Le mot-clé in peut être remplacé par of.

Expression = number

{{ i }}, 

Code HTML

<p><span v-for="i in 13">{{ i }},&nbsp;</span></p>
            

Ici, l'expression est un nombre entier positif supérieur à zéro et vaut 13. C'est la limite supérieure (comprise). Et, l'alias vaut i. C'est l'élément courant, initialisé à 1. (Et, le pas (step) vaut 1)

Il n'est pas possible de modifier la borne inférieure, ni le pas (step). Ils valent toujours 1. En réalité, lorsque l'expression est un nombre. Cela indique le nombre de fois que l'élément est répété.


Expression = string

{{ lettre }}, 

Code HTML

<p><span v-for="lettre in 'Jean Pierre'">{{ lettre }},&nbsp;</span></p>
            

Ici, l'expression est une string qui est traitée comme un tableau de caractères.


Expression = array

En pratique, la directive v-for sert à parcourir un tableau :

  • de valeurs numériques
  • de caractères ou de strings
  • d'objets (ayant un ou plusieurs couples clé:valeur)

L'index peut être utilisé avec tout type de tableau.

Tableau de valeurs numériques

{{ i }}, 

Code HTML

<p><span v-for="i in [7,8,9,10,11,12,13]">{{ i }},&nbsp;</span></p>
            

ligne in tableau. Le terme à droite de cette expression est le nom d'une variable représentant le tableau qui sera parcouru. Le terme à gauche de cette expression est le nom d'une variable représentant un élément du tableau. Le terme du milieu est le mot-clé in. Le tableau peut contenir des valeurs ou des objets.

Tableau de caractères

{{ lettre }}

Code HTML

<p><span v-for="lettre in ['T','h','i','b','a','u','t']">{{ lettre }}</span></p>
            

Tableau de strings

  1. {{ ligne }}
<ol>
  <li v-for="ligne in tableau">{{ ligne }}</li>
</ol>
  data: {
    tableau: [
      'Apprendre le HTML',
      'Étudier le CSS',
      "Coder en JavaScript"
    ]
  }

Tableau de strings (avec index)

  • {{ numLigne }} => {{ ligne }}
<ul>
  <li v-for="(ligne, numLigne) in tableau" v-on:click="getAction(numLigne)">
    {{ numLigne }} => {{ ligne }}</li>
</ul>
  methods: {
    getAction(index) {
      alert("Mon choix : " + this.tableau[index]);
    }
  }

Lorsque le terme de gauche est entouré de parenthèses, il doit être composé de deux noms de variables séparées par une virgule. Le terme de droite représente alors l'index du tableau (qui commence toujours à 0).

Tableau d'objets (contenant un couple cle:valeur)

  • {{ ligne.cle }}
<ul>
  <li v-for="ligne in tableau2">{{ ligne.cle }}</li>
</ul>
  data: {
    tableau2: [
      { cle: 'Étudier' },
      { cle: 'Apprendre' },
      { cle: "Comprendre" }
    ]
  }

Tableau d'objets (contenant plusieurs couples cle:valeur)

{{ personne.prenom }} {{ personne.nom }}
<table>
  <tr v-for="personne in personnes">
    <td>{{ personne.prenom }}</td>
    <td>{{ personne.nom }}</td>
  </tr>
</table>
  data: {
    personnes: [
      {nom: "Durand", prenom: "Jacques"},
      {nom: "Dupont", prenom: "Thibaut"},
      {nom: "Martin", prenom: "Denis"},
    }
  }

Template v-for

De la même manière qu'avec v-if, vous pouvez également utiliser la balise <template> avec v-for pour faire le rendu d'une structure contenant de multiples balises.

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-for avec v-if

il n'est pas recommandé d'utiliser v-if et v-for ensemble. Quand elle est utilisée conjointement avec v-if, v-for a une plus grande priorité que v-if.

v-for avec v-if

v-for

Voir aussi : v-for (guide), Affichage de résultats filtrés/triés

v-bind:attr_HTML

La directive v-bind permet de lier la valeur d'un attribut HTML à la valeur d'une donnée (data).

Usuellement, dans une syntaxe telle que v-bind:attr_HTML="expression", expression est le nom d'une propriété réactive (définie dans data:)

De plus, quand v-bind est utilisé avec les attributs liés à l'apparence : class="" et style="" l'expression peut évaluer des objets ou des tableaux.

Ci-dessous, toutes les syntaxes possibles :

lie un attribut (ici, src) :
<img v-bind:src="imageSrc">

nom d'attribut dynamique (2.6.0+) :
<button v-bind:[key]="value"></button>

notation abrégée :
<img :src="imageSrc">

notation abrégée d'un nom d'attribut dynamique (2.6.0+) :
<button :[key]="value"></button>

avec de la concaténation de chaînes de caractères :
<img :src="'/path/to/images/' + fileName">

liaison de classes :
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]"></div>

liaison de styles :
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>

lie un objet d'attributs :
<div v-bind="{ id: uneProp, 'autre-attr': uneAutreProp }"></div>

lie un attribut du DOM avec le modificateur prop :
<div v-bind:text-content.prop="text"></div>

liaison de prop. "prop" doit être déclaré dans mon-composant. :
<mon-composant :prop="uneValeur"></mon-composant>

transmet les props parentes à un composant enfant :
<composant-enfant v-bind="$props"></composant-enfant>

XLink :
<svg><a :xlink:special="foo"></a></svg>
Passez votre souris sur moi pendant quelques secondes pour voir mon titre lié dynamiquement !

Code HTML

<div id="app_bind">
  <span v-bind:title="message">
    Passez votre souris sur moi pendant quelques secondes
    pour voir mon titre lié dynamiquement !
  </span>
</div>

Code JS

var app_bind = new Vue({
  el: '#app_bind',
  data: {
    message: 'Vous avez affiché cette page le ' + new Date().toLocaleString()
  }
});

Usuellement, dans une syntaxe telle que v-bind:attr_HTML="expression", expression est le nom d'une propriété réactive (définie dans data:)

De plus, quand v-bind est utilisé avec les attributs HTML class="" et/ou style="" l'expression peut évaluer des objets ou des tableaux.

Mais, quand v-bind est utilisé avec l'attribut HTML style=""

La directive v-bind:attr_HTML="nom_data" ressemble à la fonction JS setAttribute().

v-bind

Voir aussi : Liaison de classes HTML, Liaison de styles HTML

v-model

Une application web est souvent liée à un formulaire.

La directive, bi-directionnelle, v-model est liée aux seules balises - <input>, <select> et <textarea> - et permet de lier la valeur de l'attribut HTML value à une donnée du modèle (data:). Ainsi, tout changement dans le contrôle est répercuté dans le modèle et comme le modèle change, la vue change.

v-model ne prend pas en compte la valeur initiale des attributs value, checked ou selected fournis par un champ. La valeur initiale doit être déclarée dans l'option data.

L'interpolation sur les zones de texte (<textarea>{{text}}</textarea>) ne fonctionnera pas. Utilisez v-model à la place.

Ceci facilite grandement la validation JS du formulaire avant l'envoi des données au serveur.

Pour faciliter la compréhension des codes ci-dessous, les attribut HTML name et value, nécessaires lors de l'envoi de données au serveur, ne sont pas présents. Cependant, ils sont nécessaires pour le contrôle du type="radio" (car il est obligatoire pour former un groupe).

Les modificateurs :

Avec la balise <input>

<input type="text" />

+++{{ message }}+++

(.trim)

+++{{ message2 }}+++

(.lazy)

+++{{ message3 }}+++

(.trim.lazy) = recommandé

+++{{ message4 }}+++

.trim.lazy = .lazy.trim

Code HTML

<form id="app5_trim">
  <p><input v-model="message" /></p>
  <pre>+++{{ message }}+++</pre>
  <p><input v-model.trim="message2" /> (.trim)</p>
  <pre>+++{{ message2 }}+++</pre>
  <p><input v-model.lazy="message3" /> (.lazy)</p>
  <pre>+++{{ message3 }}+++</pre><p>
  <input v-model.trim.lazy="message4" /> (.trim.lazy) = recommandé</p>
  <pre>+++{{ message4 }}+++</pre>
</form>

Code JS

var app5_trim = new Vue({
  el: '#app5_trim',
  data: {
    message: 'Bonjour, Thibaut !',
    message2: 'Bonjour, Léon !',
    message3: 'Bonjour, Bernard !',
    message4: 'Bonjour, Marc !'
  }
});

<input type="number" />

La valeur renvoyée d'un champ d'un formulaire est toujours une string (jamais un nombre, une date, un montant, ...). L'attribut type="number" permet de limiter les caractères à ceux nécessaires à la formation d'un nombre. Selon la configuration du navigateur, il faudra utiliser le point ou la virgule décimale.

Le modificateur .number est alors très utile.

+2 =

+2 = (.number.lazy) = recommandé

Code HTML

<p>
  <input type="number" v-model="nombre" /> +2 =
  <span v-text="result"></span>
</p>
<p>
  <input type="number" v-model.number.lazy="nombre2" /> +2 =
  <span v-text="result2"></span> (.number.lazy)
</p>

Code JS

var app5_number = new Vue({
  el: '#app5_number',
  data: {
    nombre: 1,
    nombre2: 1
  },
  computed:{
    result(){
      return this.nombre+2
    },
    result2(){
      return this.nombre2+2
    }
  }
});

<input type="radio" />

Vous avez choisi "{{sexe}}".

Ce qui est retourné lors du clic est la valeur de l'attribut value.

Code HTML

<form id="app5b" name="app5b">
  <p>
    <label>
      <input type="radio" name="sex" value="mâle" v-model="sexe" /> Sexe fort
    </label>
  </p>
  <p>
    <label>
      <input type="radio" name="sex" value="femelle" v-model="sexe" /> Sexe faible
    </label>
  </p>
  <p v-show="sexe.length">
    Vous avez choisi "{{sexe}}".
  </p>
</form>

Grâce à la directive v-show, la phrase indiquant le choix n'est pas affichée tant que le choix n'a pas été fait.

Code JS

var app5b = new Vue({
  el: '#app5b',
  data: {
    sexe: ''
  }
});

En attribuant, dans le code JS, une valeur par défaut (initiale) ne correspondant pas à celle d'un des attributs HTML value), il n'y a pas de choix par défaut, même si un choix par défaut est donné par du code HTML, checked="checked". En effet, le navigateur analyse, dans l'ordre, le code HTML, puis le code CSS et enfin le code JS. Le code JS a donc le dernier mot.

<input type="checkbox" />

Code HTML

<form id="app5c" name="app5c">
  <label>
    <input type="checkbox" v-model="isChecked" />
      Je suis <strong>{{ isChecked }}</strong>
  </label>
</form>

Code JS

var app5c = new Vue({
  el: '#app5c',
  data: {
    isChecked: false
  }
});

Avec la balise <select>

<select> : choix unique

Vous avez choisi : "{{ choix }}"

Code HTML

<form id="app5d">
  <p>
    <select v-model="choix">
      <option>&nbsp;</option>
      <option>Choix 1</option>
      <option>Choix 2</option>
      <option>Choix 3</option>
    </select>
  </p>
  <p v-show="choix.length">
    Vous avez choisi : "{{ choix }}"
  </p>
</form>

Code JS

var app5d = new Vue({
  el: '#app5d',
  data: {
    choix: []
  }
});

<select> : choix multiple

Rappel : Pour effectuer un choix multiple, il faut maintenir la touche CTRL enfoncée.

Vous avez choisi : "{{ choix }}"

Code HTML

<form id="app5d2">
  <p>
    <select v-model="choix" multiple="multiple">
      <option>&nbsp;</option>
      <option>Choix 1</option>
      <option>Choix 2</option>
      <option>Choix 3</option>
    </select>
  </p>
  <p v-show="choix.length">
    Vous avez choisi : "{{ choix }}"
  </p>
</form>

Code JS

var app5d2 = new Vue({
  el: '#app5d2',
  data: {
    choix: []
  }
});

Exemple : Remplir une liste déroulante

Vous avez choisi "{{ choix }}"

Code HTML

<form id="app5d3">
  <p>
    <select v-model="choix" multiple="multiple">
      <option v-for="option in options" v-bind:value="option.value">
        {{ option.text }}
      </option>
    </select>
  </p>
  <p v-show="choix.length">
    Vous avez choisi : "{{ choix }}"
  </p>
</form>

Code JS

var app5d3 = new Vue({
  el: '#app5d3',
  data: {
    choix: '',
    options:[
      {text:'',       value:0},
      {text:'Choix 1',value:1},
      {text:'Choix 2',value:2},
      {text:'Choix 3',value:3}
    ]
  }
});

v-model

Pour en finir avec les directives restantes, toutes d'interpolation : v-text, v-html, v-pre, v-cloak et v-once.

v-text

Les mustache permettent d'insérer du contenu dans le contenu d'une balise. Cette directive permet de remplacer le contenu de la balise.

Le contenu d'une balise est ce qui se trouve entre la balise ouvrante et la balise fermante.

Code HTML

<div id="app_text">
  <p v-text="texte"></p>
</div>

Code JS

var app_text = new Vue({
  el: '#app_text',
  data: {
    message: 'Mon texte'
  }
});

app_text.message = 'Mon autre texte'; /* = app_text.$data.message */

Un objet JS de type Vue dispose de clés. Le caractère $ précède le nom de ces clés, lorsqu'elles sont utilisées hors du constructeur de cette Vue.
$el, $data, $props, $methods, ... app7.$data.message

La directive v-text ressemble à la propriété JS .textContent

v-text

v-html

La directive v-html ressemble à la propriété JS .innerHTML. Attention aux attaques XSS ! Utilisez v-html uniquement avec du contenu de confiance et jamais avec du contenu fourni par les utilisateurs.

Code HTML

<div id="app_html">
  <p v-html="texte"></p>
</div>

Code JS

var app_html = new Vue({
  el: '#app_html',
  data: {
    message: '<u>Mon texte</u>'
  }
});

v-html

v-once

La directive v-once n'attend aucune valeur. Elle rend le contenu de la balise modifiable qu'une seule fois (et donc aussi les balises enfants).

Code HTML

<div id="app_once">
  <button> v-on="nb++">Bouton cliqué : {{ nb }} fois</button>
</div>

L'outil Tidy peut donner une valeur vide (="") aux attributs qui n'en ont pas. Ainsi, pre sera remplacé par pre=""

Code JS

var app_once = new Vue({
  el: '#app_once',
  data: {
    nb: 0
  }
});

v-once

v-cloak

Cette directive restera sur l'élément jusqu'à ce que l'instance de Vue associée ait fini sa compilation. Combiné avec des règles CSS telles que [v-cloak] { display: none }, cette directive peut être utilisée pour cacher des liaisons moustaches encore non compilées jusqu'à ce que l'instance de Vue soit prête.

L'outil Tidy peut donner une valeur vide (="") aux attributs qui n'en ont pas. Ainsi, pre sera remplacé par pre=""

v-cloak

Directives personnalisées

Il est possible de créer ses propres directives.

Directives personnalisées

filters:

L'option filters: permet de stocker des filtres qui peuvent être utilisés pour appliquer des formatages de textes courants. Les filtres sont utilisables à deux endroits : les interpolations à moustaches et les expressions de v-bind.

Dans les moustaches :
{{ message | capitalize }}

Dans les v-bind :
<div v-bind:id="rawId | formatId"></div>

filters: