Maîtriser les directives Vue.js : formulaires, filtres et extensions personnalisées

Vue.js simplifie la gestion des formulaires grâce à la directive v-model, qui établit une liaison bidirectionnelle entre les éléments de formulaire et les données de votre application.

Le comportement de v-model varie selon le type d'élément de formulaire :

  • Pour <input type="text"> et <textarea>, v-model synchronise la propriété value.
  • Pour <input type="radio">, la valeur de la propriété value de l'élément sélectionné est liée. Assurez-vous que chaque bouton radio possède une valeur distincte.
  • Pour <input type="checkbox"> :
    • Sans valeur définie, v-model gère un booléen (coché ou non).
    • Avec une valeur définie, si la donnée liée est un tableau, v-model collectera les valeurs des cases cochées dans ce tableau. Si la donnée liée n'est pas un tableau, elle recevra un booléen.
  • Pour <select>, v-model lie la valeur de l'option sélectionnée.

v-model prend également en charge des modificateurs pour ajuster son comportement :

  • .lazy : Met à jour la donnée seulement après que l'événement blur se soit produit (l'élément perd le focus).
  • .number : Tente automatiquement de convertir la valeur saisie en un nombre.
  • .trim : Supprime automatiquement les espaces blancs au début et à la fin de la chaîne saisie.
<div id="app">
 <form @submit.prevent="submitForm">
   <label for="username">Nom d'utilisateur :</label>
   <input type="text" id="username" v-model.trim="formData.username"><br><br>

   <label for="password">Mot de passe :</label>
   <input type="password" id="password" v-model="formData.password"><br><br>

   <label for="age">Âge :</label>
   <input type="number" id="age" v-model.number="formData.age"><br><br>

   <label>Genre :</label>
   <input type="radio" name="gender" value="male" v-model="formData.gender"> Homme
   <input type="radio" name="gender" value="female" v-model="formData.gender"> Femme<br><br>

   <label>Intérêts :</label>
   <input type="checkbox" v-model="formData.interests" value="coding"> Codage
   <input type="checkbox" v-model="formData.interests" value="reading"> Lecture
   <input type="checkbox" v-model="formData.interests" value="gaming"> Jeux Vidéo<br><br>

   <label for="city">Ville :</label>
   <select id="city" v-model="formData.city">
     <option value="">-- Sélectionnez --</option>
     <option value="paris">Paris</option>
     <option value="lyon">Lyon</option>
     <option value="marseille">Marseille</option>
   </select><br><br>

   <label for="bio">Biographie :</label><br>
   <textarea id="bio" v-model.lazy="formData.bio"></textarea><br><br>

   <input type="checkbox" v-model="formData.termsAccepted"> J'accepte les <a href="#">conditions d'utilisation</a><br><br>

   <button type="submit">Envoyer</button>
 </form>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
 new Vue({
   el: '#app',
   data: {
     formData: {
       username: '',
       password: '',
       age: null,
       gender: 'male',
       interests: [],
       city: '',
       bio: '',
       termsAccepted: false
     }
   },
   methods: {
     submitForm() {
       console.log('Données du formulaire :', JSON.stringify(this.formData));
       alert('Formulaire soumis ! Vérifiez la console.');
     }
   }
 });
</script>

Les filtres sont un mécanisme de formatage de texte utilisé dans Vue 2 pour transformer les données avant de les afficher dans le template. Ils sont appliqués via l'opérateur pipe (|).

Définition et utilisation :

  • Définition globale : Utilisez Vue.filter('nomFiltre', callback).
  • Définition locale : Définissez les filtres dans l'option filters de votre instance Vue.
  • Utilisatoin : {{ expression | nomFiltre }} ou v-bind:attribute="expression | nomFiltre".

Les filtres ne modifient pas les données d'origine ; ils produisent une nouvelle représentation formatée. Ils peuvent accepter des arguments et être chaînés.

Exemple d'utilisation avec une date :

Supposons que vous ayez une bibliothèque comme day.js pour la manipulation des dates.

// Utilisation locale dans l'instance Vue
new Vue({
 // ...
 data: {
   timestamp: 1678886400000 // Exemple de timestamp
 },
 filters: {
   formatDate(value, formatString = 'YYYY-MM-DD HH:mm:ss') {
     // Assurez-vous que day.js est importé
     return dayjs(value).format(formatString);
   },
   truncate(value, length = 10) {
     if (value.length > length) {
       return value.substring(0, length) + '...';
     }
     return value;
   }
 }
});
<div id="app">
 <p>Date formatée : {{ timestamp | formatDate }}</p>
 <p>Date spécifique : {{ timestamp | formatDate('DD/MM/YYYY') }}</p>
 <p>Texte tronqué : {{ longText | truncate(15) }}</p>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.7/dayjs.min.js"></script>
<script>
 // Définition globale du filtre (alternative)
 // Vue.filter('formatDate', function(value, formatString = 'YYYY-MM-DD HH:mm:ss') {
 //   return dayjs(value).format(formatString);
 // });

 new Vue({
   el: '#app',
   data: {
     timestamp: 1678886400000,
     longText: 'Ceci est un texte assez long pour tester la troncature.'
   },
   filters: {
     formatDate(value, formatString = 'YYYY-MM-DD HH:mm:ss') {
       return dayjs(value).format(formatString);
     },
     truncate(value, length = 10) {
       if (value.length > length) {
         return value.substring(0, length) + '...';
       }
       return value;
     }
   }
 });
</script>

Vue.js fournit plusieurs directives intégrées qui facilitent l'interaction avec le DOM et la gestion de l'affichage.

v-text : Affichage de contenu textuel

v-text met à jour le contenu textuel d'un élément, remplaçant tout contenu existant. Il est similaire à l'interpolation {{ }} mais remplace complètement le contenu.

<div id="app">
 <p v-text="message"></p>
 <p>Contenu initial.</p> <!-- Sera remplacé par v-text -->
</div>

<script>
 new Vue({
   el: '#app',
   data: {
     message: 'Message affiché via v-text.'
   }
 });
</script>

v-html : Rendu de HTML brut

v-html insère le contenu HTML d'une chaîne de caractères dans un élément. Attention : Utiliser cette directive avec du contenu non fiable peut entraîner des vulnérabilités XSS. À utiliser avec prudence.

<div id="app">
 <div v-html="rawHtmlContent"></div>
</div>

<script>
 new Vue({
   el: '#app',
   data: {
     rawHtmlContent: '<strong>Texte en gras</strong> et <em>en italique</em>.'
   }
 });
</script>

v-cloak : Prévention du clignotement des Mustaches

v-cloak est une directive sans valeur qui peut être combinée avec CSS pour masquer temporairement les éléments jusqu'à ce que l'instance Vue soit complètement montée. Cela évite l'affichage de {{ variable }} avant que Vue ne puisse les remplacer.

<style>
 [v-cloak] {
   display: none; /* Masque l'élément jusqu'à ce que Vue ait fini l'initialisation */
 }
</style>

<div id="app" v-cloak>
 {{ message }}
</div>

<script>
 new Vue({
   el: '#app',
   data: {
     message: 'Contenu caché puis révélé.'
   }
 });
</script>

v-once : Rendu unique pour l'optimisation

v-once permet de rendre un élément et ses enfants une seule fois. Après le rendu initial, il sera traité comme du contenu statique et ne sera plus mis à jour, même si les données sous-jacentes changent. Utile pour les parties de l'interface qui ne changent jamais.

<div id="app">
 <p v-once>Valeur initiale (ne changera pas) : {{ counter }}</p>
 <p>Valeur actuelle : {{ counter }}</p>
 <button @click="increment">Incrémenter</button>
</div>

<script>
 new Vue({
   el: '#app',
   data: {
     counter: 0
   },
   methods: {
     increment() {
       this.counter++;
     }
   }
 });
</script>

v-pre : Saut de compilation pour la performance

v-pre indique à Vue de sauter la compilation de l'élément et de ses enfants. Cela inclut les directives et l'intrepolation. C'est utile pour afficher du contenu littéral, comme des exemples de code, ou pour accélérer le rendu des sections de la page qui n'utilisent aucune directive Vue.

<div id="app">
 <p v-pre>Ce texte et les balises {{ non compilées }} ne seront pas traités par Vue.</p>
 <p>Cette partie est compilée normalement : {{ message }}</p>
</div>

<script>
 new Vue({
   el: '#app',
   data: {
     message: 'Message standard.'
   }
 });
</script>

Les directives personnalisées permettent d'étendre les fonctionnalités de Vue.js en créant vos propres directives pour manipuler le DOM de manière réactive.

Syntaxe :

  • Globale : Vue.directive('nom-directive', options).
  • Locale : Dans l'option directives de l'instance Vue.

L'objet options peut contenir des "hooks" de cycle de vie pour interagir avec l'élément lié :

  • bind(el, binding, vnode) : Appelée une seule fois, lorsque la directive est liée à l'élément pour la première fois.
  • inserted(el, binding, vnode) : Appelée lorsque l'élément lié a été inséré dans le DOM parent.
  • update(el, binding, vnode, oldVnode) : Appelée après que le composant parent ait été mis à jour, mais potentiellement *avant* que ses enfants ne soient mis à jour.
  • componentUpdated(el, binding, vnode, oldVnode) : Appelée après que le composant parent et ses enfants aient été mis à jour.
  • unbind(el, binding, vnode) : Appelée une seule fois, lorsque la directive est déliée de l'élément.

el est l'élément DOM auquel la directive est attachée. binding est un objet contenant les propriétés : name, value, oldValue, expression, arg, modifiers.

Exemple 1 : Directive personnalisée pour mettre un élément en focus

// Directive globale pour le focus automatique
Vue.directive('focus', {
 inserted: function (el) {
   el.focus(); // Met l'élément en focus lorsque celui-ci est inséré dans le DOM
 }
});
<div id="app">
 <input type="text" v-focus placeholder="Je reçois le focus automatiquement">
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
 Vue.directive('focus', {
   inserted: function (el) {
     el.focus();
   }
 });
 new Vue({ el: '#app' });
</script>

Exemple 2 : Directive pour multiplier une valeur et l'afficher

<div id="app">
 <p>Valeur originale : {{ number }}</p>
 <p>Valeur multipliée par 10 : <span v-multiply-by="number"></span></p>
 <button @click="increment">Incrémenter</button>
</div>

<script>
 new Vue({
   el: '#app',
   data: {
     number: 5
   },
   directives: {
     'multiply-by': {
       // Utilisation de `bind` et `update` pour couvrir les cas initiaux et les mises à jour
       bind: function(el, binding) {
         el.textContent = binding.value * 10;
       },
       update: function(el, binding) {
         el.textContent = binding.value * 10;
       }
     }
   },
   methods: {
     increment() {
       this.number++;
     }
   }
 });
</script>

Étiquettes: Vue.js directives formulaires v-model Filtres

Publié le 30 juillet à 22h13