Préambule
- Les démonstrations de ce TD se basent sur les sources disponibles [ ici ].
- Attention, seul le répetoire src est dans l'archive. Il faut donc créer un projet avec vue-cli et remplacer son répertoire src.
2°/ directives
2.1°/ Afficher du texte dynamique dans <p>, <span>, <li>, ...
- Il suffit d'utiliser les "moustaches" {{ }} au sein d'une balise de type <p>, <span>, <li> .etc. dans la partie template de notre composant.
- La valeur entre moustache est une expression javascript. Cela peut donc être le simplement le nom d'une variable locale (définie dans data ou calculée), un appel à une fonction, ou encore une unique instruction mais sans mot-clé de contrôle (if, for, while, ...). En revanche, on peut utiliser les opérateur logiques et arithmétiques.
- ATTENTION ! {{ }} ne permet pas d'ajouter des éléments au DOM. Donc s'il contient du HTML, c'est le code qui est affiché, pas son interprétation.
- Pour que la valeur soit interprétée, il faut utiliser l'attribut v-html de vuejs, dans la balise qui sert de point d'affichage.
- La valeur de l'attribut est le nom d'un champ de data qui contient le HTML à afficher.
Démonstration :
- Copier le fichier TD2Demo1.vue dans TD2Demo.vue
- lancer npm run serve puis visualiser le résultat dans le navigateur (par ex. http://localhost:8080)
- Montrer le code de App.vue. On constate que la valeur de la variable title est bien affiché comme un titre.
- le composant TD2Demo1 importé dans App.vue s'utilise simplement en écrivant une balise <TD2Demo1>.
- Idem pour les variables msg et htmlText définies dans TD2Demo1.
- Comme la deuxième contient du HTML, ce dernier n'est effectivement pas interprété avec {{ }}.
- On remarque qu'avec v-html, le texte interne à la balise <span> n'est pas affiché. Seul le contenu de htmlText est interprété. C'est le même comportement quelle que soit la balise.
- Modifier le contenu de msg => le texte affiché change
Remarques globales :
- ATTENTION ! Ne JAMAIS utiliser v-html sur une variable contenant une valeur fixée par une entrée utilisateur. C'est une énorme faille. Par exemple, cela permet d'injecter du javascript.
- on peut mettre entre moustache n'importe quelle variable accessible via data mais jamais des variables définies en dehors. En revanche, les attributs de data peuvent parfaitement être initialisés grâce à des variables externes.
2.2°/ Affecter la valeur d'une variable de data à un attribut de balise : v-bind
- Les moustaches doivent être utilisées à l'intérieur d'une balise.
- On ne peut donc pas les utiliser pour fixer la valeur d'un attribut de balise.
- Pour cela, vuejs propose la directive v-bind, avec la syntaxe suivante : v-bind:nom_attribut="expression_js".
- nom_attribut correspond normalement à un attribut valide pour la balise. Cela dit, si on met un nom invalide, il ne se passe rien de spécial.
- L'expression donnée après le = suit les mêmes principes que pour les moustaches : nom de champ, appel de fonction, ...
- Bien entendu, il faut que le type de la valeur retournée par l'expression corresponde au type attendu par l'attribut. Par exemple :
- les attributs à valeur booléenne (par ex. readonly) doivent être reliés à une expression renvoyant un booléen,
- l'attribut style doit être relié à un objet ou tableau contenant des couples propriété_css : valeur,
- l'attribut class doit être relié à un objet ou tableau contenant des noms de classes,
- En vuejs, l'utilisation de v-bind est extrêmement fréquente. C'est pourquoi il existe un raccourci d'écriture : il suffit d'enlever v-bind, mais en gardant les : devant le nom de l'attribut.
Démonstration :
- Copier le fichier TD2Demo2.vue dans TD2Demo.vue
- lancer npm run serve puis visualiser le résultat dans le navigateur (par ex. http://localhost:8080)
- Montrer le code de TD2Demo2. On constate que les 3 balises <input> sont bien remplies avec le prix des items associés, auxquels on concatène la chaîne ' po'
- Le premier <input> est bien en lecture seule. Mettre isReadOnly à false => on peut modifier le champ de saisie.
- Modifier un prix => la valeur du <input> change.
- Dans cet exemple, les attributs style et class sont soit affectés directement avec un tableau/objet, soit indirectement avec un champ de data contenant un tableau/objet.
- Mettre <style scoped>. Les styles définis ne s'appliquent plus qu'au composant et le titre principal de App.vue n'est plus souligné.
Remarque : v-bind peut être utilisé sur n'importe quel attribut d'une balise HTML mais également sur celles des composants. C'est un moyen de passer des valeurs aux composants sous forme de props.
2.3°/ relation bidirectionnelle : v-model
- Si la valeur du champ de saisie change, il serait pratique que la valeur du champ de data qui sert à alimenter le champ de saisie change en retour. Cette relation bidirectionnelle peut être mise ne place grâce à la directive v-model.
- Cette directive s'applique aux différents type de balise <input>. On peut donc l'utiliser sur des champs de saisie mais aussi des boutons radio et cases à cocher.
- On peut également l'utiliser avec la balise <select>
Démonstration :
- Copier le fichier TD2Demo3.vue dans TD2Demo.vue
- lancer npm run serve puis visualiser le résultat dans le navigateur (par ex. http://localhost:8080)
- Montrer le code de TD2Demo3.
- on constate que le bouton radio n°0 est bien sélectionné => relation type v-bind de selectedItem vers <input> fonctionne toujours.
- cliquer sur un autre bouton radio : le nom de l'item sélectionné change => relation de <input> vers selectedItem fonctionne également.
- sélectionner un prix d'item => la liste des prix change, signe que le champ de data a bien été modifié en retour.
2.4°/ affichage de "listes" : v-for
- Dans la démonstration précédente, on remarque que le code devient très vite redondant dès lors que l'on manipule des éléments d'un tableau.
- Fort heureusement, vuejs propose la directive v-for permettant d'itérer sur un tableau ou sur les champs d'un objet pour instancier plusieurs fois une même balise, mais avec des valeurs d'attribut différentes.
- Grâce à la balise <div> sur laquelle on utilise v-for, on peut même répéter plusieurs fois plusieurs balises.
- La syntaxe v-for est multiple, selon qu'on l'applique à un tableau, un objet, que l'on désire récupérer les indices dans le tableau, les noms de champs dans l'objet. Quelques exemples :
- v-for = "el in tab" : el prendra successivement comme valeur chaque élément de tab
- v-for = "(el, idx) in tab" : idem et idx vaudra 0, 1, ...
- v-for = "(val, name, idx) in obj" : val prendra successivement comme valeur chaque valeur de champ dans obj, name sera le nom de champ et idx vaudra 0,1, ...
- Dans ces exemples, le nom des itérateurs est au choix du développeur. On peut donc remplacer el, idx, val, name par ce que l'on veut, du moment qu'on l'utilise dans le reste de la (ou les) balise(s) utilisant v-for.
- IMPORTANT : lorsque l'on utilise la configuration par défaut créée par vue-cli, l'utilisation de v-for sur une balise implique de donner une valeur à son attribut key. Comme il faut que cette valeur soit différente pour chaque balise créée avec v-for, on utilise très souvent l'index comme valeur (cf. démonstration).
Démonstration :
- Copier le fichier TD2Demo4.vue dans TD2Demo.vue
- lancer npm run serve puis visualiser le résultat dans le navigateur (par ex. http://localhost:8080)
- Montrer le code de TD2Demo4.
- Cet exemple fait la même chose que le précédent, avec en plus, le parcours des champs de l'item sélectionné.
- On remarque que pour le v-for du <div> qui affiche la liste des items, on a pas besoin de fixer l'attribut key pour les balises répétées mais juste dans <div>.
- On remarque également que les attributs id et for utilisés dans ce <div> sont cette fois affectés grâce à v-bind. Normal car leur valeur doit être différente pour chaque entrée de la liste à puce. donc elle est calculée grâce à une expression javascript.
- Enfin, même si on ne gagne pas beaucoup de lignes de code pour cet exemple, on imagine aisément le gain lorsque le tableau que l'on doit parcourir a plusieurs dizaine/centaines d'éléments. Qui plus est, v-for fonctionne toujours, même si la taille du tableau évolue !
Remarques :
- on peut imbriquer des v-for. C'est particulièrement utile lorsque l'on veut générer une balise <table>, par ex, à partir un tableau dont les éléments contiennent eux-mêmes des tableaux
- pour nue même balise, on peut utiliser conjointement v-for et v-bind, par exemple pour passer des valeurs d'attributs différentes selon l'instance de la balise.
- v-for s'applique à toute balise HTML mais aussi celles des composants.
2.5°/ affichage conditionnel : v-if, v-else-if, v-else
- Grâce à v-bind, on peut générer des changements de valeur/style conditionnels.
- En revanche, cela ne permet pas de carrément changer de balise de façon conditionnelle.
- Pour cela, il existe les directives v-if, v-else-if, qui prennent en paramètre une expression JS (comme les moustache et v-bind), et v-else, qui n'a pas de paramètre.
- Ces directives permettent de créer dans le DOM un ou plusieurs éléments en fonctions de l'évaluation true ou false de l'expression.
- Attention ! ces directives ne s'appliquent qu'à la balise où elles apparaissent. Cela implique que sauf exception, le rendu conditionnel ne fonctionnera pas sur des balises imbriquées.
- Parmi les exceptions : balises <div> et <template>.
Démonstration :
- Copier le fichier TD2Demo5.vue dans TD2Demo.vue
- lancer npm run serve puis visualiser le résultat dans le navigateur (par ex. http://localhost:8080)
- Montrer le code de TD2Demo5.
- La première partie de la page illustre le fait que les balises utilisé dans v-if, v-else-if et v-else peuvent être différentes.
- La seconde partie illustre l'utilisation de v-if sur <div>. C'est le seul moyen (avec template) de rendre conditionnel l'affichage de tout un ensemble de balises. Bien entendu, celles-ci doivent être imbriquées dans <div>