Pour votre progression, c'est très important de finir le sujet précédent avant de commencer celui-ci.
Vous devez travailler connectés (lien « Connexion » en haut à droite de la page). Sinon, vous rencontrerez des problèmes d'avancement et vous risquez d'être comptés absent. En étant connectés vous retrouverez l'endroit où vous en étiez à la séance suivante.
La commande « npm init » crée un seul fichier. Comment s'appelle-t-il ?
Vous êtes sur la bonne voie. Le nom commence bien par « pack ... »
« node_modules » est un répertoire et il n'est pas crée par « npm init »
Vous avez écrit un fichier JS exemple.js
Que faut-il taper dans la ligne de commande pour l’exécuter en utilisant Node JS ?
Vous êtes sur la bonne voie. On utilise bien la commande « node »
Où s’exécute (ou est principalement utilisé) le code suivant ?
(Dans l'utilisation qu'on en a faite dans ces TP)
package.json
simple_fetch
document.queryselector
npm
app.get('/hello',(requete,reponse)=>{reponse.send('Bonjour');});
fs.readFile
En Node.js, que faut-il écrire au début d'un fichier JS pour utiliser une autre librairie.
Donnez juste le premier mot.
Oui, on peut utiliser require, mais on a fait le choix dans ce cours d'utiliser autre chose.
Vue.js est un framework frontend pour construire des pages web ayant beaucoup d'interactions.
Vue.js a des points communs avec React, Angular, Svelte et d'autres.
Ces frameworks sont souvent utilisés pour construire des « single page applications », c'est à dire des sites où l'utilisateur reste sur la même page et toutes les interactions sont gérées par JS et Ajax.
Dans l'approche classique, la navigation se fait en cliquant sur des liens ou en appuyant sur des boutons de formulaires. A chaque fois une nouvelle page (P) est visitée. La page visitée peut avoir des interactions JS, mais, en général, elles ne changent pas l'essentiel de l'affichage de la page. De temps en temps une interaction AJAX (A) peut venir enrichir cette navigation.
À l'autre extrême, dans une SPA, une seule page (P) est chargée et l'utilisateur ne la quitte pas. L'utilisateur interagît avec cette page de manière complexe et l'affichage peut changer complètement. Ces interactions sont gérées en JS avec des appels AJAX (A) fréquents.
Dans une SPA, certaines fonctionnalités du navigateur, comme le bouton retour arrière / avant et l'ouverture d'un lien dans un autre onglet,...), posent problème.
Faites les liens
L'utilisateur reste sur la même page, même quand il clique sur des éléments de la page
Quand l'utilisateur clique sur un lien, il change de page
Les interactions de l'utilisateur sont en général gérées en JS
De nombreuses requêtes AJAX sont nécessaires.
Une grande différence entre Vue.js et ce qu'on a fait précédemment, est l'approche « déclarative ».
Jusqu'à présent, on partait d'une page HTML et on la modifiait à partir du JS quand l'utilisateur interagissait (click, clavier, ...).
En pratique, une page HTML est généralement construite (par exemple en PHP) à partir de données.
Quand les interactions JS deviennent importantes, on se retrouve à reconstruire en JS une bonne partie du HTML à partir de données modifiées:
données => HTML <= modification des données et du HTML par JS
On construit donc le HTML de deux manières très différentes. Ça conduit à des incohérences. Par ailleurs, modifier du HTML en JS est beaucoup plus compliqué que d'écrire du HTML.
Dans une approche déclarative, on décrit une seule fois comment construire le HTML à partir des données. Quand les données changent, la page se met à jour automatiquement. On a donc:
donnés => HTML
Prenons un exemple très très simple:
La donnée est « age », et on on veut la faire passer de 25 à 26 quand l'utilisateur clique sur un bouton.
PHP:
$age=25;
echo '<h1>Age: '.$age.'<h1>';
echo '<input type="button" value="bouton"/>';
Ensuite, en JS:
document.querySelector('input').addEventListener('click',()=>{
document.querySelector('h1').textContent='Age:'+26;
});
En JS, on a voulu changer l'age, on a donc du retrouver le h1 et le modifier. Ce code JS est compliqué par rapport à l'écriture du HTML.
Si les propriétaires veulent maintenant afficher « Mon age est: 25 » au lieu de « Age: 25 », le développeur va devoir changer à la fois le code PHP et le code JS. S'il oublie l'un où l'autre, ce sera incohérent.
...
let age=ref(25);
function changer(){
age.value=26;
}
template:
<h1>Age: {{age}}</h1>
<input type="button" value="bouton" @click="changer"/>
Quand l'utilisateur clique sur le bouton, la fonction « changer » change uniquement la variable age. La page se met automatiquement à jour. Aucun besoin d'écrire du JS compliqué pour modifier le DOM. Si les propriétaires de la page veulent maintenant afficher « Mon age
est: 25 » au lieu de « Age: 25 », le développeur va juste modifier le template, ce qui est relativement simple.
Quelles affirmations sont vraies ?
En Vue.js, on modifie juste des variables. La page se met à jour toute seule.
En Vue.js, on utilise souvent document.querySelector pour aller chercher des éléments DOM.
Dans l'approche traditionnelle, on crée d'abord une page à partir de données. Ensuite, si l'utilisateur clique quelque part et change ces données, on doit mettre à jour le DOM en JS.
Quelles affirmations sont vraies ?
(rappel)
En Vue.js, on crée des variables « réactives ». Quand ces variables sont modifiées, cela déclenche une mise à jour de l'affichage de la page.
Dans une interface classique PHP (sur le serveur) et JS (dans le navigateur), tout le code pour générer la page HTML est dans le PHP.
Non. Le JS met aussi à jour le HTML (en fait le DOM).
C'est plus simple d'écrire du code JS+DOM que du code HTML
Ouf... beaucoup de théorie! Essayons Vue.js en pratique...
Désarchivez le fichier vue-hello.tgz
Rentrez dans le répertoire « vue-hello » et regardez les fichiers.
On est bien dans un paquet Node.js.
Quel est le nom du paquet dont dépend ce paquet ?
package.json n'est pas un paquet, c'est un fichier.
C'est lui qui définit le nom de votre projet, et beaucoup d'autres informations intéressantes.
Lisez-le.
Rappelez-vous des cours précédents. Il y a un fichier où on peut trouver l'information cherchée...
(rappels)
Dans ce fichier, un champ "dependencies" décrit les paquets (libraires) dont il a besoin pour fonctionner.
« vue-hello » a uniquement besoin du paquet « vue »... c'est le paquet qui contient Vue.js !
Il y a un autre champs appelé « devDependencies » dans package.json
Ce sont les paquets dont on a besoin pour développer.
Quelle commande faut-il taper pour pouvoir utiliser tout ça ?
Presque!
Indice: Vous avez précisé trop de choses.
Vous êtes sur la bonne voie. C'est bien une commande « npm ».
Tapez la commande
$ npm run dev
Ceci lance un serveur de développement et affiche son URL : http://locahost:5173 (Attention: ce numéro de port - 5173 - peut changer)
Ouvrez l'URL affichée.
Et voila ! Votre première App Vue.js 😊
Avec ce serveur de développement, appelé « vite », quand vous modifiez le code, la page se recharge toute seule!
Découvrons tous les fichiers. Prenez le temps de les lire.
Quel est le fichier contenant le texte « Hello world » ?
Presque! Vérifiez l'orthographe.
App.vue est un fichier « .vue » avec trois parties:
En Vue.js, votre application est construite avec des « composants ». Chaque fichier « .vue » est un composant.
Il contient tout ce qu'il faut pour que ce composant marche (JS, HTML, CSS).
Dans le template, on peut afficher des variables.
Remplacez le <h1> par:
<h1>Hello {{nom}}</h1>
Ceci va afficher la variable « nom ».
Dans le script, ajoutez:
let nom='Tom';
Essayez d'afficher le titre en rouge.
Dans le navigateur, regardez le code source HTML (Ctrl+U).
Cherchez un fichier similaire dans vos répertoires. Comment s'appelle-t-il ?
Lisez index.html
Il ne contient pas grande chose.
Dans le <body> il y a juste un <div> et un <script>.
Quel est le « id » du <div> ?
Le <script> appelé dans index.html est src/main.js
Regardez le fichier src/main.js
Il est vraiment très simple:
En regardant dans src/main.js, où dans la page index.html est installé App.vue ?
(donnez le « id »)
Regardons plus en détail la syntaxe d'un fichier « .vue »
Dans un <template>, on veut écrire du HTML qui affiche des données.
Il y a deux types d'endroits où on peut afficher des variables et même des expressions JS:
Dans le contenu (« texte ») d'une balise, on utilise {{ ... code JS ... }} :
<template>
<h1>Hello {{nom}}, {{1+1}}, {{nom+123}}</h1>
</template>
Essayez dans App.vue
Dans un attribut d'une balise, on utilise « : » devant le nom de l'attribut. La valeur de l'attribut est alors considérée comme du JS:
<template>Essayez dans App.vue
<h1>Hello {{nom}}</h1>
<input type="button" :value="nom" />
<input type="button" :value="'hello'+nom"/>
</template>
<script setup>
let nom='Karim';
let score=300;
</script>
<template>
<h1>XYZ</h1>
</template>
Que faut-il écrire à la place de XYZ pour afficher « Le joueur Karim a 300 points » ?
Utilisez les variables nom et score.
Essayez dans App.vue, avant de répondre.
Presque. Vous avez bien utilisé {{ nom }} et {{ score }}.
Le problème est autour. (probablement une erreur de frappe)
<script setup>
let nom='Tom';
let couleur='red';
</script>
<template>
<h1>Hello {{nom}}</h1>
</template>
Re-écrivez toute la ligne du h1 pour qu'il s'affiche avec la couleur qui se trouve dans la variable « couleur ».Presque! Vous avez commencé par:
<h1 :style="'color:'+couleur"
ce qui est correct. Le problème est après.
Vous êtes sur la bonne voie. Vous avez commencé par:
<h1 :style="
ce qui est correct. Le problème est après.
Oui, on peut utiliser {color: ...}, qui est la manière standard de faire, mais qui utilise une syntaxe (les {...}) qu'on n'a pas encore vue.
Pour l'instant essayez d'utiliser vos connaissances existantes sur la propriété « style ».
Vous devez récrire toute la ligne du <h1...
Donc votre réponse doit commencer par <h1 ...
Vous ne pouvez pas utiliser {{ ... }} à l'intérieur d'une balise ouvrante:
Faux: <p class="{{ }}" > ...</p>
Pour les attributs il faut utiliser les « : » devant le nom de l'attribut « :nomattribut ».
La valeur de l'attribut est alors considérée comme du JS:
Ok: <p :abcd="2+2">...</p>
Vous n'avez pas utilisé l'attribut « :style »
Pour gérer les événements on ajoute un attribut avec un « @ » suivi du nom de l'événement.
Pour l'instant, la valeur de l'attribut sera juste le nom de la fonction.
<script setup>
let nom='Tom';
function exemple(){
console.log('ca marche!');
}
function exemple2(e){
console.log('input',e.target.value);
}
</script>
<template>
<h1 @click="exemple">Hello {{nom}}</h1>
<input @keyup="exemple2" />
</template>
Essayez dans App.vue
<script setup>
function bouger(e){
console.log('input',e.pageX);
}
</script>
<template>
<div id="cadre" XYZ></div>
</template>
<style scoped>
#cadre{
width: 300px;
height: 300px;
border: 1px solid black;
}
</style>
On voudrait que la fonction « bouger » soit appelée chaque fois que l'utilisateur bouge la souris sur le cadre.
Que faut-il écrire à la place de XYZ ?
Essayez dans App.vue, avant de répondre.
(rappel événements)
Vous êtes sur la bonne voie. Votre réponse commence par
@mousemove ...
ce qui est correct. Le problème est après.
<script setup>
let nom='Tom';
function exemple(){
}
</script>
<template>
<h1 @click="exemple">Hello {{nom}}</h1>
</template>
Copiez ceci dans App.vue
À l'intérieur de la fonction exemple(), changez la variable « nom ».
Est-ce que la nouvelle valeur de « nom » s'affiche quand vous cliquez sur le <h1> ?
Est-ce que l'affichage du h1 se met à jour ?
non
oui
Dans cet exemple, l'affichage de « Hello Tom » n'est pas mis à jour quand on fait nom='Leila'
<script setup>
let nom='Tom';
function exemple(){
console.log('click');
nom='Leila';
}
</script>
<template>
<h1 @click="exemple">Hello {{nom}}</h1>
</template>
En effet, Vue.js ne sait pas que la variable « nom » a changé. Il ne sait donc pas qu'il faut mettre à jour l'affichage.
Pour que Vue.js le sache, on doit crée des variables réactives. C'est un concept important.
<script setup>
import {ref,reactive} from 'vue';
let nom=ref('Tom');
function exemple(){
console.log('click');
nom.value='Leila';
}
</script>
<template>
<h1 @click="exemple">Hello {{nom}}</h1>
</template>
Essayez dans App.vue. Cliquez sur le <h1>
<script setup>
import {ref,reactive} from 'vue';
let user=reactive({nom:'Tom',age: 25});
function exemple(){
console.log('click');
user.nom='Leila';
}
</script>
<template>
<h1 @click="exemple">Hello {{user.nom}}, Age: {{user.age}}</h1>
</template>
Essayez dans App.vue. Cliquez sur le <h1><script setup>
import {ref,reactive} from 'vue';
let a1='x';
let a2=ref('x');
let a3=ref('x');
function f1(){a1='y';}
function f2(){a2.value='y';}
function f3(){a3='y';}
</script>
<template>
<p @click="f1">{{a1}}</p>
<p @click="f2">{{a2}}</p>
<p @click="f3">{{a3}}</p>
</template>
Quelles affirmations sont vraies ?
(Sans essayer dans App.vue)
Quand l'utilisateur clique sur le 2e paragraphe, celui-ci affiche « y »
Quand l'utilisateur clique sur le 1er paragraphe, celui-ci affiche « y »
Non, la variable a1 n'est pas réactive. Vue.js ne sait pas qu'elle a été changée dans la fonction f1() ... Vue.js ne met donc pas à jour l'affichage.
Quand l'utilisateur clique sur le 3e paragraphe, celui-ci affiche « y »
Non, regardez bien f3. Il y a un problème.
La fonction f3 contient une erreur.
La fonction f3 contient bien une erreur. En effet, a3 est crée par ref(), il faut donc utiliser « a3.value »
<script setup>
import {ref,reactive} from 'vue';
XYZ
</script>
Que faut-il écrire à la place de XYZ pour créer une variable « age » qui contienne le nombre 20 et qui soit réactive ?
Non. La fonction « reactive » est uniquement pour les objets et les tableaux. Ici, il s'agit d'un nombre.
Vous êtes sur la bonne voir. Le début de votre réponse est correct:
let age=ref( ...
Le problème est après.
<script setup>
import {ref,reactive} from 'vue';
let age=ref(20);
XYZ
</script>
Que faut-il écrire à la place de XYZ pour changer l'age à 25 ?
Non, comme « age » a été crée avec ref(), vous ne pouvez pas changer directement sa valeur.
<script setup>
import {ref,reactive} from 'vue';
XYZ
</script>
Que faut-il écrire à la place de XYZ pour créer un tableau « noms » qui contienne les noms 'Tom', 'Leila' et 'Joe', et qui soit réactif ?
Presque! La réponse commence bien par:
let noms=reactive ...
Le problème est après.
Non, dans ce cours on utilise ref() uniquement pour les valeurs simples (string, number). Ici on a un tableau.
<script setup>Que faut-il écrire à la place de XYZ pour changer 'Joe' en 'Enzo' ?
import {ref,reactive} from 'vue';
let noms=reactive(['Tom','Leila','Joe']);
XYZ
</script>
Non. Quand vous utilisez « reactive(...) », vous ne devez pas utiliser « .value »
C'est quand vous utilisez « ref(...) » que vous devez utiliser « .value »
noms est un tableau indexé par des nombres, pas un objet indexé par des chaînes de caractères.
<script setup>Quand la souris se déplace dans le cadre, affichez la coordonnée x dans le span.
import {ref,reactive} from 'vue';
function bouger(e){
console.log('input',e.pageX);
}
</script>
<template>
<p>Position X: <span></span></p>
<div id="cadre" @mousemove="bouger"></div>
</template>
<style scoped>
#cadre{
width: 300px;
height: 300px;
border: 1px solid black;
}
</style>
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
<script setup>
import {ref,reactive} from 'vue';
let x=ref(0);
function bouger(e){
console.log('input',e.pageX);
x.value=e.pageX;
}
</script>
<template>
<p>Position X: <span>{{x}}</span></p>
<div id="cadre" @mousemove="bouger"></div>
</template>
<style scoped>
#cadre{
width: 300px;
height: 300px;
border: 1px solid black;
}
</style>
<script setup>
import {ref,reactive} from 'vue';
let x=ref(0);
function bouger(e){
console.log('input',e.pageX);
x.value=e.pageX;
}
</script>
<template>
<img id="piece" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/piece-chat.svg"/>
<div id="cadre" @mousemove="bouger"></div>
</template>
<style scoped>
#cadre{
width: 300px;
height: 300px;
border: 1px solid black;
}
#piece{
position: absolute;
top: 0;
}
</style>
Faites en sorte que la position « left » de l'image soit indiquée par la variable « x ».
Indice: utilisez l'attribut « style »
(rappel)
Vérifiez que l'image bouge.
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
<script setup>
import {ref,reactive} from 'vue';
let x=ref(0);
function bouger(e){
console.log('input',e.pageX);
x.value=e.pageX;
}
</script>
<template>
<img id="piece" :style="'left:'+x+'px'" src="https://moodle.iutv.univ-paris13.fr/img/bjs2/piece-chat.svg"/>
<div id="cadre" @mousemove="bouger"></div>
</template>
<style scoped>
#cadre{
width: 300px;
height: 300px;
border: 1px solid black;
}
#piece{
position: absolute;
top: 0;
}
</style>
<script setup>
import {ref,reactive} from 'vue';
</script>
<template>
<p>Le joueur {{nom}} a 500 points.</p>
<p>Le joueur {{nom}} a fini le niveau 3.</p>
<p>Le joueur {{nom}} est classé 4e.</p>
<input />
</template>
<style scoped>
</style>
Quand l'utilisateur tape un nom dans le champs texte, il s'affiche aux endroits indiqués par {{nom}}.
Indices:
<script setup>
import {ref,reactive} from 'vue';
let nom=ref('Tom');
function touche(e){
nom.value=e.target.value;
}
</script>
<template>
<p>Le joueur {{nom}} a 500 points.</p>
<p>Le joueur {{nom}} a fini le niveau 3.</p>
<p>Le joueur {{nom}} est classé 4e.</p>
Nom: <input @keyup="touche" />
</template>
<style scoped>
</style>
Continuons à creuser la syntaxe d'un fichier « .vue »
Pour l'instant, on a mis le nom d'une fonction dans l'attribut événement (@click, @keyup, ...).
function touche(){ ... }
...
<input @keyup="touche" />
On peut aussi y mettre directement du code JS. On peut y utiliser des variables ref() sans « .value ». Par exemple:
<input type="button" @click="c++" />Le code JS peut être une fonction fléchée:
<input @keyup="e=>nom=e.target.value" />
Nom: <input @keyup="nom=$event.target.value" />On ne peut pas, malheureusement, utiliser directement console.log, ni alert:
Nom: <input @keyup="console.log('ceci ne sera pas affiché')" />
Voici un exemple complet. Essayez-le.
<script setup>
import {ref,reactive} from 'vue';
let c=ref(0);
let nom=ref('Tom');
</script>
<template>
<p>Le joueur {{nom}} a {{c}} points.</p>
<p>Le joueur {{nom}} a fini le niveau 3.</p>
<p>Le joueur {{nom}} est classé 4e.</p>
Nom: <input @keyup="e=>nom=e.target.value" />
Nom: <input @keyup="nom=$event.target.value" />
<input type="button" @click="c++" value="cliquer"/>
</template>
<style scoped>
</style>
On veut souvent afficher une suite de choses dans un template. On a donc besoin de boucles.
Vue.js permet de faire différentes sortes de boucles en utilisant l'attribut « v-for ».
Voyons une boucle très simple:
<template>
<span v-for="i in 10">Hello {{i}}</span>
</template>
Cette boucle crée 10 <span>. Attention, la valeur « i » va de 1 à 10 (et non pas de 0 à 9).
Complétez les « ... » pour afficher un tableau comme ceci:
<script setup>
import {ref,reactive} from 'vue';
</script>
<template>
<table>
...
</table>
</template>
<style scoped>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 70px;
height: 70px;
text-align: center;
}
</style>
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur,
puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
<script setup>
import {ref,reactive} from 'vue';
</script>
<template>
<table>
<tr><td v-for="colonne in 7">{{colonne}}</td></tr>
</table>
</template>
<style scoped>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 70px;
height: 70px;
text-align: center;
}
</style>
Complétez le code précédent pour afficher 6 lignes, comme ceci:
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
<script setup>
import {ref,reactive} from 'vue';
</script>
<template>
<table>
<tr v-for="ligne in 6">
<td v-for="colonne in 7">{{ligne}},{{colonne}}</td>
</tr>
</table>
</template>
<style scoped>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 70px;
height: 70px;
text-align: center;
}
</style>
Créez une variable « tableau » avec un tableau JS contenant 7 chaînes vides
(pour l'instant, sans qu'il soit reactive)
Pour l'instant, on ne veut le faire sans « reactive ». On l'ajoutera plus tard.
Modifiez le code suivant pour obtenir ceci:
Attention: n'oubliez pas que v-for va de 1 à 7 alors que le tableau JS est indexé de 0 à 6
<script setup>
import {ref,reactive} from 'vue';
let tableau=['','','','c','','s',''];
</script>
<template>
<table>
<tr v-for="ligne in 6">
<td v-for="colonne in 7">{{ligne}},{{colonne}}</td>
</tr>
</table>
</template>
<style scoped>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 70px;
height: 70px;
text-align: center;
}
</style>
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
On voudrait construire un tableau JS à 2 dimensions. Il suffit de faire un tableau contenant d'autres tableaux.
Par exemple:
let tableau= [
['a','b','c'],
['d','e','f'],
];
tableau[1] est le tableau ['d','e',f']
pour obtenir « f » on pourrait donc faire : (tableau[1])[2]
les parenthèses n'étant pas nécessaires, on peut tout simplement écrire: tableau[1][2]
Modifiez votre code pour créer un tableau JS avec 6 lignes et 7 colonnes et affichez ceci:
Écrivez le code, vérifiez qu'il fonctionne dans votre navigateur, puis copiez-le ici pour que votre enseignant puisse le relire plus tard:
<script setup>
import {ref,reactive} from 'vue';
let tableau=[
['c','' ,'' ,'' ,'' ,'' ,'s'],
['' ,'' ,'' ,'' ,'' ,'' ,'' ],
['' ,'' ,'' ,'' ,'' ,'' ,'' ],
['' ,'' ,'' ,'' ,'' ,'' ,'' ],
['' ,'' ,'' ,'' ,'' ,'' ,'' ],
['s','' ,'' ,'' ,'' ,'' ,'c'],
];
</script>
<template>
<table>
<tr v-for="ligne in 6">
<td v-for="colonne in 7">{{tableau[ligne-1][colonne-1]}}</td>
</tr>
</table>
</template>
<style scoped>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 70px;
height: 70px;
text-align: center;
}
</style>