Généralités
Vue.js 3 est une plateforme de développement front-end moderne, offrant une architecture réactive et une composition de composants performante pour la création d'interfaces utilisateur dynamiques et évolutives. Cette version apporte de nombreuses améliorations en termes de performance, d'API plus propre et de nouvelles fonctionnalités, telles que la composition API, qui simplifie la gestion de l'état et les interactions entre les composants.
Installation de Vue.js
L'installation de Vue.js peut varier en fonction de notre environnement, dans cette partie
nous utiliserons les CDN pour pouvoir débuter l'utilisation de Vue.js le plus vite possible.
Un fichier de base utilisant des liens CDN est disponible ici :
download
Les variables
En Vue.js, on peut gérer les variables de deux manières principales :
Variables non réactives let ou const
Ce sont des variables JavaScript standard. Les modifications apportées à ces variables ne sont pas automatiquement détectées par Vue.js. On devra mettre à jour manuellement les parties de notre application qui dépendent de ces variables.
Variables réactives ref
La fonction ref crée une référence réactive à une valeur (tableau, objet ou primitive). On accède à la valeur réelle de la variable réactive à l'aide de l'attribut value. Les changements apportés à value sont automatiquement détectés par Vue.js, ce qui met à jour les parties de notre application qui dépendent de cette variable de manière automatique.
Déclarations de variables réactives
let users = ref([]);
let error = ref(null);
let count = ref(0);
let message = ref('');
message.value = "Bonjour à tous.";
content_copy
Un peu plus sur le const
const garantit que la variable ne peut pas être réassignée
à une nouvelle valeur ou référence.
Si c'est un type primitif (nombre, chaîne, booléen, etc.), on ne peut pas changer la valeur.
Si c'est un objet ou un tableau, on ne peut pas changer l'objet ou le tableau référencé,
mais on peut modifier ses propriétés ou éléments internes.
Exemple avec un type primitif
const x = 10;
x = 20; // Erreur ! On ne peut pas réassigner x à 20.
Exemple avec un objet ou un tableau
const arr = [1, 2, 3];
arr[0] = 10; // Cela fonctionne, car on modifie le contenu du tableau, pas la référence.
arr = [4, 5, 6]; // Erreur ! On ne peut pas réassigner la variable 'arr' à un nouveau tableau.
const obj = { name: "Toto" };
obj.name = "Bob"; // Cela fonctionne, car on modifie une propriété de l'objet.
obj = { name: "Charlie" }; // Erreur ! On ne peut pas réassigner 'obj' à un nouvel objet.
Les objets
En Vue.js, les objets permettent de créer des variables contenant plusieurs attributs. Cela facilite la gestion de données complexes en les regroupant de manière structurée.
Création d'un objet
const message_object = ref({
show: false,
message: "",
color: ""
});
content_copy
Modifier une valeur d'un objet
function updateVisibility(bool) {
message_object.value.show = bool;
}
content_copy
Modifier toutes les valeurs d'un objet
Méthode 1
function updateAll(newValues) {
Object.assign(message_object.value, newValues);
}
// Usage
updateAll({ show: true, message: "Toto", color: "red" });
content_copy
Méthode 2
function updateAll(newValues) {
message_object.value = { ...newValues }; // Réaffectation directe avec déstructuration
}
content_copy
Utilisation
<div v-if="message_object.show">
<p :class="[message_object.color]">
{{ message_object.message }}
</p>
</div>
content_copy
Les inputs
On peut gérer les entrées d'utilisateurs dans des éléments de formulaire
pour modifier une variable réactive en utilisant la directive v-model.
La directive v-model lie l'élément de formulaire à une variable réactive.
De plus, nous utilisons des conditions pour afficher une phrase en fonction de l'âge.
<!-- HTML -->
<div class="change-value mt-3">
<input type="number" v-model="age" placeholder="Entrez votre âge" />
<h2 v-if="age >= 18">Vous êtes majeur.</h2>
<p v-else-if="age >= 13">Vous êtes mineur mais adolescent.</p>
<p v-else>Vous êtes mineur.</p>
</div>
// VueJs
let age = ref(18);
content_copy
Les selects
Les menus déroulants selects sont des composants importants en HTML. Dans cet exemple, nous allons voir comment les manipuler avec Vue.js 3, en sélectionnant une couleur à appliquer à un élément div HTML.
<!-- HTML -->
<select class="form-select" aria-label="Vue js select example" v-model="selectedOption">
<option v-for="option in options" :key="option.value" :value="option.value">
{{ option.text }}
</option>
</select>
<p>Selected option: {{ selectedOption }}</p>
<div :class="['box', selectedOption]"></div>
content_copy
// Vue.js
// Déclaration et initialisation du tableau d'options
const options = [
{ value: null, text: 'Open this select menu' },
{ value: "blue", text: 'Blue' },
{ value: "green", text: 'Green' },
{ value: "red", text: 'Red' }
];
let selectedOption = ref(null);
return {
options,
selectedOption,
};
content_copy
Selected option: {{ selectedOptionExample }}
Les cases à cocher
Dans cette partie, il y aura un exemple de comment fonctionne les cases à cocher en Vue.js :
Checkbox
<div class="mb-3">
<label class="form-label">Sélectionnez vos fruits préférés</label>
<div v-for="fruit in fruits" :key="fruit.id" class="form-check">
<input class="form-check-input" type="checkbox" :id="'fruit-' + fruit.id" :value="fruit.id" v-model="selectedFruits"/>
<label :for="'fruit-' + fruit.id" class="form-check-label">
{{ fruit.name }}
</label>
</div>
<p>Selected option: {{ selectedFruits }}</p>
</div>
content_copy
const fruits = ref([
{ id: 1, name: 'Orange'},
{ id: 2, name: 'Banane'},
{ id: 3, name: 'Poire'},
{ id: 4, name: 'Annanas'},
]);
content_copy
Bindings (Liaisons) dynamiques
En Vue.js, nous pouvons manipuler les propriétés des éléments HTML de manière déclarative en utilisant des Bindings. Voici une liste de quelques possibilités pour gérer les attributs d'un élément HTML en Vue.js :
Fonctionnement
la balise Vue est v-bind (ou la syntaxe abrégée :)
Eléments HTML
-disabled
Pour désactiver un bouton en fonction d'une condition :
<button class="btn btn-sm btn-success" @click="toggleDisableBtn">Changer l'état du bouton</button>
<button class="btn btn-sm btn-secondary" :disabled="isBtnDisabled">Bouton</button>
content_copy
const isBtnDisabled = ref(true);
function toggleDisableBtn() {
isBtnDisabled.value = !isBtnDisabled.value;
}
content_copy
Exemple Interactif
-class
Lier une classe CSS à sa version active en fonction d'une variable Vue.js :
<button class="btn btn-sm btn-primary" @click="activeBox">Activer la boîte</button>
<div class="another-class box" :class="{ active: isBoxActive }">
Une boîte à activer.
</div>
content_copy
.another-class { box-shadow: 0px 0px 80px rgba(0, 0, 0, 0.17); }
.box {
width: 150px;
height: 150px;
padding: 10px;
background-color: blueviolet;
color: #fff;
}
.box.active { border: 5px solid green; }
content_copy
const isBoxActive = ref(false);
function activeBox() {
isBoxActive.value = !isBoxActive.value;
}
content_copy
-Gestion de plusieurs classes
On peut ajouter ou enlever des classes CSS en fonction de variables Vue :
<div class="d-flex gap-2">
<button type="button" class="btn btn-sm btn-secondary" @click="addStyleOne">
{{ styleOne ? '-' : '+' }} Style 1
</button>
<button type="button" class="btn btn-sm btn-secondary" @click="addStyleTwo">
{{ styleTwo ? '-' : '+' }} Style 2
</button>
<button type="button" class="btn btn-sm btn-secondary" @click="addStyleThree">
{{ styleThree ? '-' : '+' }} Style 3
</button>
</div>
<div
class="box-ex-binding"
:class="{
'box-ex-binding-border': styleOne,
'text-center-box-ex-binding': styleTwo,
'border-color-box-ex-binding': styleThree
}">
<p>Exemple de boîte.</p>
</div>
content_copy
.box-ex-binding {
width: 100px;
height: 100px;
padding: 10px;
margin-top: 5px;
background-color: blueviolet;
}
.box-ex-binding p {
margin: 0;
text-align: center;
}
// Btn Style 1
.box-ex-binding-border { border-radius: 10px; }
// Btn Style 2
.text-center-box-ex-binding { text-align: center; }
// Btn Style 3
.border-color-box-ex-binding { border: 5px solid #28af1c; }
content_copy
const styleOne = ref(false);
const styleTwo = ref(false);
const styleThree = ref(false);
// Ajoute la class : box-ex-binding-border
function addStyleOne() {
styleOne.value = !styleOne.value;
}
// Ajoute la class : text-center-box-ex-binding
function addStyleTwo() {
styleTwo.value = !styleTwo.value;
}
// Ajoute la class : border-color-box-ex-binding
function addStyleThree() {
styleThree.value = !styleThree.value;
}
content_copy
Exemple Interactif
Exemple de boîte.
-Gestion de plusieurs classes et conditions ternaires
Pour une interface utilisateur plus dynamique, il est intéressant de pouvoir personnaliser la couleur d'un bouton selon la valeur d'une variable réactive Vue.js.
<button @click="renderDiv" :class="['btn btn-sm', enableRender ? 'btn-warning' : 'btn-success']">
{{ enableRender ? 'Cacher le rendu' : 'Afficher le rendu' }}
</button>
// Vue
const enableRender = ref(false);
function renderDiv() {
enableRender.value = !enableRender.value;
}
content_copy
Exemple interactif
-style
Lier des styles CSS à un élément en fonction d'une expression Vue.js :
<button :style="{ color: textColor }">Contenu</button>
content_copy
-Attributs booléens
Gérer les attributs booléens des éléments HTML, comme required, checked, readonly, etc.
<input type="checkbox" v-model="isChecked" :checked="isChecked" />
content_copy
- Attribuer une classe CSS en fonction d'un booléen
On peut utiliser des opérateurs ternaires pour déterminer quelle classe affecter en fonction d'une valeur booléenne :
:class="user.all_payments_true ? 'btn-warning' : 'btn-secondary'"
content_copy
-Attributs généraux
On peut également lier n'importe quel attribut HTML avec v-bind :
Supposons que nous avons une boucle v-for qui parcourt une collection
récupérée par une requête Axios. Si on souhaite créer des modals en fonction de cette collection :
<tr v-for="(file, index) in files" :key="file.id">
<td>
<span v-if="file.comment === null" class="material-icons">visibility_off</span>
<div v-else>
<a data-bs-toggle="modal" :data-bs-target="'#showComment_'+file.id" class="material-icons color_2 cursor">visibility</a>
<!-- Modal comment -->
<div class="modal fade modal-close" :id="'showComment_'+file.id" tabindex="-1" aria-labelledby="" aria-hidden="true">
...
</div>
</div>
</td> <!-- Comments -->
</tr>
content_copy
Manipulation des Tableaux
Création d'un tableau
let fruits_1 = ref[];
let fruits = ref['Pommes', 'Bananes', 'Cerises'];
content_copy
Ajout d'éléments au tableau
let fruits = ref['Pommes', 'Bananes', 'Cerises'];
fruits.value.push('Poires');
content_copy
Suppression d'éléments
let fruits = ref['Pommes', 'Bananes', 'Cerises'];
fruits.value.splice(index, 1);
content_copy
Mise à jour d'un élément
let fruits = ref['Pommes', 'Bananes', 'Cerises'];
fruits.value[1] = 'Abricot';
content_copy
Les boucles
En Vue.js on peut utiliser des boucles sur des élements HTML, facilitant ainsi la manipulation des données, l'affichage des données.
for
La directive Vue v-for permet de parcourir une structure de données et d'afficher son contenu dans le HTML.
<!-- HTML -->
<ul>
<li v-for="fruit in fruits" :key="fruit">
@{{ fruit }}
</li>
</ul>
// VueJs
let fruits = ['Pommes', 'Bananes', 'Cerises'];
content_copy
Dans Vue.js, la boucle for s'utilise de façon similaire à d'autres langages de programmation, en utilisant les index :
const factures = ref([
{ id: 1, name: 'toto', prix: 45.4, },
{ id: 2, name: 'tata', prix: 14.5, },
{ id: 3, name: 'titi', prix: 78.8, },
{ id: 4, name: 'tutu', prix: 22.35, },
]);
function loopWithFor() {
for (let i=0; i < factures.value.length; i++) {
console.log("Nom : "+factures.value[i].name+" Prix : "+factures.value[i].prix);
}
}
content_copy
Dans Vue.js, la boucle for of est idéale pour parcourir des itérables (tableaux, chaînes, etc.) quand on n'a pas besoin de l'index :
for of
- Itère sur les valeurs des objets itérables (tableaux, chaînes, Map, Set, etc.).
- Ne fonctionne pas directement sur les objets simples.
- Parcourt les valeurs de l'itérable.
const factures = ref([
{ id: 1, name: 'toto', prix: 45.4, },
{ id: 2, name: 'tata', prix: 14.5, },
{ id: 3, name: 'titi', prix: 78.8, },
{ id: 4, name: 'tutu', prix: 22.35, },
]);
function loopWithForOf() {
for (let facture of factures.value) {
console.log("Nom : "+facture.name+" Prix : "+facture.prix);
}
}
content_copy
La différence principale entre for...of et for...in réside
dans leur utilisation et ce qu'ils itèrent :
for in
- Itère sur les propriétés énumérables d'un objet.
- Utilisé principalement pour les objets (pas recommandé pour les tableaux).
- Parcourt les clés (noms de propriétés) de l'objet.
const personne = ref({
nom: 'ILLOURMANE',
prenom: 'Mahmoud',
age: 26,
profession: 'Ingénieur',
ville: 'Reims'
});
function loopWithForIn() {
for (let propriete in personne.value) {
console.log(propriete + " : " + personne.value[propriete]);
}
}
content_copy
forEach
La méthode forEach est une façon très pratique et lisible de parcourir les éléments d'un tableau.
const factures = ref([
{ id: 1, name: 'toto', prix: 45.4, },
{ id: 2, name: 'tata', prix: 14.5, },
{ id: 3, name: 'titi', prix: 78.8, },
{ id: 4, name: 'tutu', prix: 22.35, },
]);
function loopWithForEach() {
factures.value.forEach(facture => {
console.log("Nom : "+facture.name+" Prix : "+facture.prix);
});
}
content_copy
La méthode forEach accepte jusqu'à trois paramètres dans sa fonction de rappel :
factures.value.forEach((element, index, array) => {
console.log("Nom : "+element.name+" Prix : "+element.prix);
});
content_copy
Signification de chaque paramètre
- element : L'élément courant du tableau sur lequel
forEach est en train d'itérer.
- index : L'index de l'élément courant dans le tableau.
- array : Le tableau complet sur lequel forEach est appelé.
const factures = ref([
{ id: 1, name: 'toto', prix: 45.4, },
{ id: 2, name: 'tata', prix: 14.5, },
{ id: 3, name: 'titi', prix: 78.8, },
{ id: 4, name: 'tutu', prix: 22.35, },
]);
function loopWithForEach() {
factures.value.forEach((facture, idx, array) => {
// Afficher les détails de la facture
console.log(`Nom : ${facture.name} | Prix : ${facture.prix}`);
// Afficher l'index de la facture
console.log(`Index : ${idx}`);
// Afficher le tableau complet
console.log(`Tableau complet :`, array);
// Ajouter un commentaire pour chaque facture
console.log(`Commentaire : La facture ${facture.name} a un prix de ${facture.prix} et se trouve à l'index ${idx}.`);
});
}
content_copy
Dans cet exemple, le but est de supprimer un champ précis.
Il y aura deux approches : l'une consiste à supprimer la case
dans le tableau original, et l'autre consiste à
utiliser map pour créer un nouveau
tableau sans le champ.
Exemple avec l'utilisation de map
const factures = ref([
{ id: 1, name: 'toto', prix: 45.4, },
{ id: 2, name: 'tata', prix: 14.5, },
{ id: 3, name: 'titi', prix: 78.8, },
{ id: 4, name: 'tutu', prix: 22.35, },
]);
// SUPPRIME LE CHAMP "NAME" SUR LE TABLEAU ORIGINAL
function removeNameOriginal() {
factures.value.forEach(facture => {
delete row.name;
});
}
content_copy
- ID : {{ facture.id }}, {{ facture.name ? facture.name + ',' : '' }} {{ facture.prix }}
map
La méthode map est utilisée pour transformer les données d'un tableau. Elle crée systématiquement un nouveau tableau contenant les résultats de l'application d'une fonction donnée à chaque élément du tableau original. Cette méthode est particulièrement utile lorsqu'on souhaite effectuer une manipulation uniforme sur tous les éléments sans modifier le tableau d'origine.
const valeurs = [1, 2, 3, 4, 5];
function loopWithMap1() {
let newValues = valeurs.map(valeur => valeur * 2);
console.log("Nouvelles valeurs : "+newValues);
}
content_copy
L'opérateur de décomposition (...) en JavaScript permet d'étendre ou de copier les
propriétés d'un objet ou les éléments d'un tableau. Il est très utile lorsqu'on utilise map.
Dans cet exemple, le but est de rajouter la TVA à chacun des prix, et de
créer un nouveau tableau contenant la nouvelle propriété :
const factures = ref([
{ id: 1, name: 'toto', prix: 45.4, },
{ id: 2, name: 'tata', prix: 14.5, },
{ id: 3, name: 'titi', prix: 78.8, },
{ id: 4, name: 'tutu', prix: 22.35, },
]);
function loopWithMap2() {
let facturesAvecTVA = factures.value.map(facture => ({
...facture,
prixTTC: (facture.prix * 1.20).toFixed(2),
}));
console.log("Factures avec TVA :", facturesAvecTVA);
}
content_copy
Dans cet exemple, le but est de montrer comment en utilisant map on peut copier un tableau en n'incluant pas un champ spécifique du tableau originale.
const factures = ref([
{ id: 1, name: 'toto', prix: 45.4, },
{ id: 2, name: 'tata', prix: 14.5, },
{ id: 3, name: 'titi', prix: 78.8, },
{ id: 4, name: 'tutu', prix: 22.35, },
]);
function removeNameCopy() {
// Crée une nouvelle copie du tableau sans le champ 'name'
return factures.value.map(({ name, ...rest }) => rest);
}
content_copy
Tableau originale :
- ID : {{ facture.id }}, NAME : {{ facture.name }}, PRICE : {{ facture.prix }}
Nouveau tableau
- ID : {{ facture.id }}, PRICE : {{ facture.prix }}
Les conditionnelles
En Vue.js on peut utiliser des conditionnelles sur des élements HTML, facilitant ainsi la manipulation des données, l'affichage des données.
<!-- HTML -->
<div>
<p v-if="isLoggedIn">Bienvenue, utilisateur !</p>
<p v-else>Veuillez vous connecter.</p>
</div>
// VueJs
let isLoggedIn = ref(false);
content_copy
Les formulaires
Dans cette partie nous allons regarder comment on peut manipuler les formulaires.
Les formulaires
Le but de cette section est de montrer comment créer un formulaire et récupérer les données :
@submit
Lorsqu'on crée un formulaire en Vue.js, il faut prendre en compte la manière de le gérer. On utilise des liaisons d'événements, dont il existe deux principaux types :
- Comportement : Avec cette approche, on associe l'événement submit à une
méthode spécifique définie dans l'objet Vue (dans cet exemple, la méthode s'appelle myFun).
- Utilisation : On l'utilise lorsqu'on souhaite exécuter une logique personnalisée lors de la
soumission du formulaire, comme valider les données ou envoyer une requête Axios.
- Effet : Lorsque le formulaire est soumis, la méthode myFun est appelée.
Si cette méthode ne contient pas event.preventDefault(),
le comportement par défaut de soumission du formulaire se produira.
<form @submit="myFun">
<!-- Champ Nom -->
<div>
<label for="nom">Nom:</label>
<input type="text" v-model="nom">
</div>
<!-- Champ Prénom -->
<div>
<label for="prenom">Prénom:</label>
<input type="text" v-model="prenom">
</div>
<!-- Champ Date de Naissance -->
<div>
<label for="date_naissance">Date de Naissance:</label>
<input type="date" v-model="dateNaissance">
</div>
<!-- Champ Adresse Mail -->
<div>
<label for="email">Adresse Mail:</label>
<input type="email" v-model="email">
</div>
<!-- Champ Mot de Passe -->
<div>
<label for="mot_de_passe">Mot de Passe:</label>
<input type="password" v-model="motDePasse">
</div>
<button type="submit">Envoyer</button>
</form>
<!-- Affichage des données du formulaire -->
<div>
<h2>Données du formulaire:</h2>
<p>Nom: {{ nom }}</p>
<p>Prénom: {{ prenom }}</p>
<p>Date de Naissance: {{ dateNaissance }}</p>
<p>Email: {{ email }}</p>
<p>Mot de Passe: {{ motDePasse }}</p>
</div>
content_copy
// Code vue.js
// Variables réactives
const nom = ref('');
const prenom = ref('');
const dateNaissance = ref('');
const email = ref('');
const motDePasse = ref('');
function myFun() {
event.preventDefault();
console.log("ok");
}
// Retourner les variables pour les utiliser dans le template
return {
nom,
prenom,
dateNaissance,
email,
motDePasse,
myFun
};
content_copy
- Comportement : Utilise la directive .prevent
pour empêcher l'action par défaut de l'événement submit, qui, dans un formulaire
classique, est l'envoi des données au serveur et le rechargement de la page.
- Utilisation : Cette approche n'appelle pas de fonction spécifique,
ce qui la rend moins lisible.
<form @submit.prevent>
<!-- Champ Nom -->
<div>
<label for="nom">Nom:</label>
<input type="text" v-model="nom">
</div>
<!-- Champ Prénom -->
<div>
<label for="prenom">Prénom:</label>
<input type="text" v-model="prenom">
</div>
<!-- Champ Date de Naissance -->
<div>
<label for="date_naissance">Date de Naissance:</label>
<input type="date" v-model="dateNaissance">
</div>
<!-- Champ Adresse Mail -->
<div>
<label for="email">Adresse Mail:</label>
<input type="email" v-model="email">
</div>
<!-- Champ Mot de Passe -->
<div>
<label for="mot_de_passe">Mot de Passe:</label>
<input type="password" v-model="motDePasse">
</div>
<button type="submit">Envoyer</button>
</form>
<!-- Affichage des données du formulaire -->
<div>
<h2>Données du formulaire:</h2>
<p>Nom: {{ nom }}</p>
<p>Prénom: {{ prenom }}</p>
<p>Date de Naissance: {{ dateNaissance }}</p>
<p>Email: {{ email }}</p>
<p>Mot de Passe: {{ motDePasse }}</p>
</div>
content_copy
// Code vue.js
// Variables réactives
const nom = ref('');
const prenom = ref('');
const dateNaissance = ref('');
const email = ref('');
const motDePasse = ref('');
// Retourner les variables pour les utiliser dans le template
return {
nom,
prenom,
dateNaissance,
email,
motDePasse
};
content_copy
- Utilisation : Cette approche combine les deux méthodes précédentes. Elle empêche la soumission du formulaire tout en appelant la fonction correspondante.
<form @submit.prevent="submitForm">
<!-- Champ Nom -->
<div>
<label for="nom">Nom:</label>
<input type="text" v-model="nom">
</div>
...
<button type="submit">Envoyer</button>
</form>
content_copy
Watch & WatchEffect
Les fonctions watchEffect et watch permettent toutes deux d'observer et de réagir aux changements des données réactives. Cependant, elles se distinguent par leur fonctionnement et leurs cas d'utilisation spécifiques.
- Fonctionnement : elle exécute une fonction immédiatement lors de la création, puis à chaque fois que les données réactives utilisées à l'intérieur de cette fonction changent le code de la fonction s'exécute de nouveau.
Exemple d'utilisation de watchEffect
Dans cet exemple le but est d'activer ou désactiver un bouton en fonction de la taille d'un tableau. Nous avons un tableau réactif que l'on peut modifier en ajoutant ou supprimant des éléments. Le bouton (Supprimer) sera désactivé si le tableau ne contient qu'un seul élément. Le bouton (Ajouter) sera désactivé si on atteint 10 éléments dans le tableau.
<!-- Code HTML -->
<p>Nombre d'éléments : {{ items.length }}</p>
<button class="btn btn-primary" @click="addItem" :disabled="isAddedDisabled">Ajouter un élément</button>
<button class="btn btn-danger" @click="removeItem" :disabled="isRemoveDisabled">Supprimer un élément</button>
<div class="items">
<div v-for="(item, index) in items" :key="index" :class="['item', item.color]">
{{ item.value }}
</div>
</div>
content_copy
// Tableau réactif où chaque élément contient une valeur et une couleur associée
const items = ref([ {value:'Elément 1', color: getRandomColor()} ]);
// Variable réactif pour contrôler l'état du bouton "Supprimer"
const isRemoveDisabled = ref(false);
// Variable réactif pour contrôler l'état du bouton "Ajouter"
const isAddedDisabled = ref(false);
// Fonction pour ajouter un élément au tableau avec une couleur aléatoire
function addItem() {
if(items.value.length <= 9) {
items.value.push({
value: `Elément ${items.value.length + 1}`,
color: getRandomColor(),
});
}
}
// Fonction pour supprimer un élément du tableau
function removeItem() {
if(items.value.length > 0) {
items.value.pop();
}
}
function getRandomColor() {
const colors = ['green', 'red', 'blueviolet'];
return colors[Math.floor(Math.random() * colors.length)];
}
// watchEffect pour activer/désactiver le bouton "Supprimer"
watchEffect(() => {
isRemoveDisabled.value = items.value.length <= 1;
isAddedDisabled.value = items.value.length >= 10;
});
content_copy
Affecter directement une fonction à un watchEffect
Plutôt que d'écrire le code avec la syntaxe () => { ... }, il est possible de créer une fonction séparée et de l'affecter directement.
function buttonsEffect() {
isRemoveDisabled.value = items.value.length <= 1;
isAddedDisabled.value = items.value.length >= 10;
}
watchEffect(buttonsEffect);
content_copy
Nombre d'éléments : {{ items.length }}
Lorsqu'on utilise watch, il est nécessaire de spécifier explicitement les
propriétés à surveiller. Dans notre exemple, nous surveillons la longueur du tableau item.
- Fonctionnement : Dans le cas d'un tableau, il est important de déterminer si
l'on souhaite appeler watch à chaque modification du tableau ou uniquement lorsque sa taille change.
Cela donne lieu à des comportements différents, comme dans les deux exemples suivants :
// Surveillance uniquement de la longueur du tableau 'items'
watch(() => items.value.length, (newLength) => {
isRemoveDisabled.value = newLength <= 1;
isAddedDisabled.value = newLength >= 10;
}, { immediate: true });
// Surveillance de tout changement dans le tableau 'items'
watch(() => items.value, (newLength) => {
isRemoveDisabled.value = newLength <= 1;
isAddedDisabled.value = newLength >= 10;
}, { immediate: true });
content_copy
Explication des différences :
- Surveiller la longueur (items.value.length) : La méthode watch
sera déclenchée uniquement lorsque des éléments seront ajoutés ou supprimés du tableau (lorsque la taille change).
- Surveiller le tableau en entier (items.value) : Ici, la méthode sera déclenchée pour toute
modification dans le tableau, que ce soit un ajout, une suppression ou même un changement dans les éléments du tableau,
à condition que l'on utilise l'option { deep: true } pour une surveillance en profondeur
des objets internes.
L'option deep
L'option deep dans Vue 3 est utilisée dans le watch pour surveiller en profondeur les objets ou les tableaux réactifs.
Par défaut, watch ne détecte pas les changements au sein des propriétés internes d'un objet ou d'un tableau réactif,
à moins que l'objet entier ne soit remplacé. En d'autres termes, si on modifies directement une propriété ou un élément interne,
watch ne sera pas déclenché.
Lorsqu'on ajoutes l'option { deep: true }, on indiques à Vue de surveiller toutes les propriétés
ou éléments internes de l'objet ou du tableau, de manière récursive. Cela signifie que le watch sera déclenché même
si on modifies une propriété interne sans remplacer l'objet dans sa totalité.
Exemple
const obj = ref({ name: "Mahmoud", age: 26 });
watch(obj, (newVal) => {
console.log("L'objet a changé !");
});
// Si on modifies une propriété interne de l'objet
obj.value.name = "ILLOURMANE"; // Le 'watch' ne sera pas déclenché ici
content_copy
const obj = ref({ name: "Mahmoud", age: 26 });
watch(obj, (newVal) => {
console.log("L'objet a changé !");
}, { deep: true });
// Modification d'une propriété interne
obj.value.name = "ILLOURMANE"; // Le 'watch' sera déclenché cette fois
content_copy
Nous allons maintenant reprendre l'exemple précédent, mais cette fois en utilisant watch :
<!-- Le même code HTML que watchEffect -->
content_copy
// Seul le code watch change
// Utilisation de watch pour surveiller la longueur du tableau items
// la fonction de rappel est déclenchée avec la nouvelle longueur comme 'newLength'
watch(() => items.value.length, (newLength) => {
isRemoveDisabled.value = newLength <= 1;
isAddedDisabled.value = newLength >= 10;
}, { immediate: true });
content_copy
Watch & fonction
Lorsqu'on surveille une variable réactive, on lui fournit une fonction qui sera appelée à chaque fois que la variable change :
Approche N°1
const nameRegex = /^[A-Za-z]+(?:-[A-Za-z]+)*$/;
const lastName = ref('Mahmoud');
function validateName(nameToValidate) {
if (nameRegex.test(nameToValidate)) {
console.log("OK");
} else {
console.log("KO");
}
}
watch(lastName, (newValue, oldValue) => {
validateName(newValue);
}, { immediate: true }
);
content_copy
Approche N°2
// Regex
const nameRegex = /^[A-Za-z]+(?:-[A-Za-z]+)*$/;
const lastName = ref('Mahmoud');
function validateName() {
if (nameRegex.test(lastName.value)) {
console.log("OK");
} else {
console.log("KO");
}
}
watch(lastName, validateName, { immediate: true });
content_copy
Conclusion sur les deux approches
- Approche 1 : On peut passer n'importe quelle valeur à la fonction
validateName, ce qui la rend plus flexible et réutilisable. Cela est utile
si plusieurs variables doivent être validées avec la même fonction.
- Approche 2 : On accède directement à lastName.value
dans validateName, ce qui rend cette méthode plus simple et directe, surtout si
validateName sera toujours utilisé avec lastName.
Cette approche est légèrement plus concise et peut être préférée lorsqu'il n'est pas nécessaire de
passer des arguments supplémentaires.
Exemple interactif
Nombre d'éléments : {{ items.length }}
Exemple complet de validation d'un formulaire
HTML
<form @submit.prevent="submitForm">
<div class="mb-3 last-name">
<label class="form-label">Nom <strong class="c_red">*</strong></label>
<div class="input-group">
<span class="input-group-text material-icons">badge</span>
<input type="text" class="form-control" v-model="lastName" required>
</div>
</div>
<div class="mb-3 first-name">
<label class="form-label">Prénom <strong class="c_red">*</strong></label>
<div class="input-group">
<span class="input-group-text material-icons">badge</span>
<input type="text" class="form-control" v-model="firstName" required>
</div>
</div>
<div class="mb-3 email">
<label class="form-label">Adresse mail <strong class="c_red">*</strong></label>
<div class="input-group">
<span class="input-group-text material-icons">alternate_email</span>
<input type="email" class="form-control" v-model="emailAddress" required>
</div>
</div>
<div class="mb-3 phone-number">
<label class="form-label">Numéro de téléphone</label>
<div class="input-group">
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">{{ phoneIndicator }}</button>
<ul class="dropdown-menu">
<li v-for="(code, country) in countryCodes" :key="country">
<a class="dropdown-item" @click="selectCode(code)">{{ country }} ({{ code }})</a>
</li>
</ul>
<input type="number" class="form-control" v-model="phoneNumber">
</div>
</div>
<div class="mb-3 date-birth">
<label class="form-label">Date de naissance</label>
<div class="input-group">
<span class="input-group-text material-icons">calendar_month</span>
<input type="date" class="form-control" v-model="dateOfBirth">
</div>
</div>
<div class="d-grid">
<button class="btn btn-sm btn-success btn-rounded" :disabled="!isFormValid">Ajouter un utilisateur</button>
</div>
</form>
content_copy
VUE
// Regex
const nameRegex = /^[A-Za-z]+(?:-[A-Za-z]+)*$/;
const phoneNumberRegex = /^[0-9]{9}$/;
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// Champs du formulaire
const lastName = ref('');
const firstName = ref('');
const emailAddress = ref('');
const phoneIndicator = ref('Indicatif');
const phoneNumber = ref(null);
const dateOfBirth = ref(null);
// États de validation
const isLastNameValid = ref(false);
const isFirstNameValid = ref(false);
const isEmailValid = ref(false);
const isPhoneNumberValid = ref(true);
const countryCodes = ref({
"Algérie": "+213",
"Allemagne": "+49",
"Angleterre": "+44",
"Belgique": "+32",
"Canada": "+1",
"Espagne": "+34",
"France": "+33",
"Italie": "+39",
"Luxembourg": "+352",
"USA": "+1"
});
// #region Fonctions de validations
const validateName = (name, valueToValidate) => {
valueToValidate.value = name && nameRegex.test(name);
}
const validateEmail = () => {
isEmailValid.value = emailAddress.value && emailRegex.test(emailAddress.value);
}
const validatePhone = () => {
// Si le champ est vide, on considère qu'il est valide car optionnel
isPhoneNumberValid.value = !phoneNumber.value || phoneNumberRegex.test(phoneNumber.value);
}
// #endregion END/Fonctions de validations
// #region Watchers
watch(lastName, () => validateName(lastName.value, isLastNameValid))
watch(firstName, () => validateName(firstName.value, isFirstNameValid))
watch(emailAddress, validateEmail)
watch(phoneNumber, validatePhone)
// #region END/Watchers
// Computed pour vérifier la validité globale du formulaire
const isFormValid = computed(() => {
return isLastNameValid.value && isFirstNameValid.value && isEmailValid.value && isPhoneNumberValid.value;
})
// Fonction de soumission du formulaire
function submitForm() {
if (isFormValid.value) {
// Logique de soumission du formulaire
console.log('Formulaire soumis')
} else {
console.log('Formulaire invalide')
}
}
function selectCode(code) {
phoneIndicator.value = code;
}
content_copy
Exemple interactif
Fonctions
En Vue.js on peut définir les fonctions de différentes manières :
Function Expression
Syntaxe
La première définition utilise la syntaxe de fonction fléchée const incrementCount = () => { count.value++; };. C'est une Function Expression qui assigne une fonction anonyme à une constante const. Les fonctions fléchées sont plus courtes et peuvent être utilisées de manière plus concise.
Portée
Dans le cas d'une expression de fonction, la fonction utilise la portée léxicale lexical scope. Cela signifie que this dans la fonction fléchée est lié à la portée dans laquelle elle est définie (c'est-à-dire this sera le même que dans la fonction parent). Cela rend la gestion de la portée de this plus simple.
const incrementCount = () => {
count.value++;
};
content_copy
Function Declaration
Syntaxe
La deuxième définition est une déclaration de fonction classique function incrementCount() { count.value++; }. Elle déclare une fonction nommée de manière plus traditionnelle.
Portée
Dans le cas d'une Function Declaration, this est dynamique et dépend de l'endroit où la fonction est appelée. Cela peut conduire à une confusion ou des erreurs dans certains contextes.
function incrementCount() {
count.value++;
}
content_copy
Composants et paramètres
Le but de Vue.js est de créer des composants réutilisables. Pour ce faire, nous avons besoin que ces composants acceptent des paramètres lors de leur appel. Cela nous permet d'utiliser le même composant, qui effectue une tâche spécifique, sur plusieurs pages tout en affichant ou en traitant des données différentes.
Du parent vers l'enfant
Dans ce premier exemple, le but est de créer un composant qui accepte en paramètre un endpoint HTTP d'API (ou autre) et qui retourne un message (à l'intérieur du composant enfant).
Composant 1/2
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script setup>
import { ref, defineProps, onMounted } from 'vue';
// Définir les props que le composant acceptera
const props = defineProps({
endPoint: {
type: String,
required: true
}
});
const message = ref('');
</script>
<style scoped>
</style>
content_copy
Composant 2/2 (Requête Axios)
// A ajouter dans le code du 1/2
// ...
// Requête Axios et affichage
onMounted(async ()=> {
printMessage();
});
/*
* Permet d'afficher le message retourner par le endPoint
**/
async function printMessage() {
try {
const response = await getRequest();
const statusCode = response.status;
if (statusCode === 200) {
message.value = response.data.message;
}
} catch (error) {
// Aucune gestion d'erreur dans cet exemple
console.error("ERREUR : " + error);
}
}
/*
* Permet d'effectuer une requête Axios
**/
async function getRequest() {
try {
const response = await axios.get(`${props.endPoint}`);
return response;
} catch (error) {
throw(error);
}
}
content_copy
Appel du composant
// Appel du composant dans un template HTML
<test-component-params end-point="/get-message"></test-component-params>
content_copy
Laravel
// Le endpoint est /get-message
public function returnMessage() {
// Le message a retourner
$message = "Un composant avec des paramètres c'est chouette.";
return response()->json([
'message' => $message,
], 200);
}
content_copy
Flask
@app.route('/get-message', methods=['GET'])
def return_message():
if request.method != 'GET':
return jsonify({"error": "Method Not Allowed"{), 405
# Le message a retourner
message = "Un composant avec des paramètres c'est chouette."
return jsonify({'message': message{), 200
content_copy
Hapi Js
server.route({
method: 'GET',
path: '/get-message',
handler: (request, h) => {
// Le message à retourner
const message = "Un composant avec des paramètres c'est chouette.";
return h.response({
message: message
}).code(200);
}
});
content_copy
Composants et paramètres sur Vue.js 2
Vue.js 2.4
var app = new Vue({
el: '#app',
props: {
endPoint: {
type: String,
required: true
}
},
data() {
return {
message: ''
};
},
mounted() {
// Requête Axios vers l'endPoint fourni
this.printMessage();
},
methods: {
async printMessage() {
try {
const response = await axios.get(this.endPoint);
if (response.status === 200) {
this.message = response.data.message;
}
} catch (error) {
console.error('Erreur lors de la requête :', error);
}
}
}
});
content_copy
Appel du composant
<test-component-params end-point="/get-message"></test-component-params>
content_copy
Du composant enfant vers le parent
Le but de cet exemple est de retourner une valeur d'un composant enfant vers le composant parent qui l'appel.
Compsant enfant
On commence par créer le composant HTML ou la requête HTTP que l'on souhaite transmettre au composant parent.
<template>
<span>Saisir un âge</span>
<input type="number" v-model="age">
<button class="button" @click="sendDataToParent()">Envoyer</button>
</template>
content_copy
Compsant enfant
Dans la section du code, il est nécessaire d'importer l'événement
defineEmits. Ensuite, nous devons créer une variable
au sein d'un tableau qui contiendra toutes les variables à transmettre au composant parent.
Grâce à la fonction sendDataToParent, nous appelons
la méthode emit de Vue.js, en spécifiant quelle
variable du tableau emit nous souhaitons utiliser
pour transmettre notre variable age.
<script setup>
import { ref, defineEmits } from 'vue';
// Création d'un émetteur d'événements
const emit = defineEmits(['dataToReceive']);
// La variable à transmettre
const age = ref(null);
// La fonction qui émit la donnée
function sendDataToParent() {
if (!age.value) {
console.warn("LA SAISIE DE L'AGE EST OBLIGATOIRE.");
return;
}
emit('dataToReceive', age.value);
}
</script>
content_copy
Composant parent
Dans le composant parent, on appelle le composant et on spécifie ce qu'il faut faire lorsque l'on reçoit la variable de la part du composant enfant. On utilise la syntaxe @nom_variable_attendu="fonction_qui_la_manipulera".
<child-component
@dataToReceive="handleReceiveData"
>
</child-component>
content_copy
Composant parent
Ensuite, on manipule la donnée reçue comme on le souhaite.
const data = ref(null);
function handleReceiveData(data) {
data.value = data;
}
content_copy
Composants et paramètres sur Vue.js 2
Vue.js 2.4
var app = new Vue({
el: '#app',
data() {
return {
age: null,
};
},
methods: {
sendDataToParent() {
if (!this.age) {
console.warn("LA SAISIE DE L'AGE EST OBLIGATOIRE.");
return;
}
// Émettre l'événement avec la donnée
this.$emit('dataToReceive', this.age);
}
}
});
content_copy
Appel du composant depuis le parent
<template>
<div>
<child-component @dataToReceive="handleData" />
<>Âge reçu de l'enfant : {{ receivedAge }}</>
</div>
</template>
...
data() {
return {
receivedAge: null,
};
},
methods: {
handleData(age) {
this.receivedAge = age;
},
},
content_copy
Opérations CRUD
Dans cette section, nous examinerons en détail les diverses opérations CRUD (Create, Read, Update, Delete) en utilisant Vue.js 3, Laravel 10, Flask et Hapi Js.
Une requête Axios
Le code suivant montre le squelette type d'une requête Axios, il démontre comment vérifier les différents codes HTTP renvoyés par le serveur :
// Cette fonction effectue une requête Axios POST
async function postAddRole() {
const dataToSend = {
roleName: roleName.value
};
try {
const response = await axios.post('/role/create-roles', dataToSend);
return response;
} catch (err) {
throw err;
}
}
async function handleAddRole(event) {
event.preventDefault();
try {
const response = await postAddRole();
const statusCode = response.status;
// A CE STADE ON NE PEUT CAPTER QUE LA PLAGE DE 2XX
if (statusCode === 200) {
console.log("REQUETE OK");
return;
} else {
console.log("Erreur requête");
return;
}
} catch (err) {
// VERIFICATION DE SI L'ERREUR A UNE REPONSE ET UN CODE DE STATUT
if (err.response) {
// LA REQUETE A ETE FAITE ET LE SERVEUR A REPONDU AVEC UN CODE DE STATUT QUI SORT DE LA PLAGE DE 2XX
console.log('Erreur dans err.response :', err.response);
const statusCode = err.response.status;
// EXEMPLE DE CAPTURE SPECIFIQUE
if (statusCode === 400) {
console.log('Erreur 400 : Mauvaise requête');
console.log('Détails de l\'erreur 400 :', err.response.data);
} else {
// GESTION D'AUTRES CODES D'ERREUR HTTP
console.log('Erreur HTTP :', statusCode);
console.log('Détails de l\'erreur :', err.response.data);
}
} else if (err.request) {
// LA REQUETE A ETE FAITE MAIS AUCUNE REPONSE N'A ETE RECUE
console.log('Aucune réponse reçue :', err.request);
} else {
// QUELQUE CHOSE S'EST MAL PASSE LORS DE LA CONFIGURATION DE LA REQUETE
console.log('Erreur :', err.message);
}
}
}
content_copy
Gestion des erreurs
Pour simplifier la gestion des erreurs attendues côté client, on peut utiliser une fonction qui permet d'indiquer en paramètres les erreurs attendues et de les traiter plus facilement.
/**
* Gère les erreurs HTTP de manière flexible et personnalisée.
*
* @param {Error} error - L'objet erreur de la requête HTTP.
* @param {number[]} arrayHttpErrors - Un tableau contenant les codes d'erreur HTTP à surveiller.
*/
function handleErrors(error, arrayHttpErrors) {
if (error.response) {
const { status, data } = error.response;
// Vérifie si le code d'erreur figure dans le tableau spécifié
if (arrayHttpErrors.includes(status)) {
const errorMessage = data.errors || data.error || 'Erreur non spécifiée';
console.error(`Erreur ${status}:`, errorMessage);
// Gestion spéciale pour le statut 422
if (status === 422 && Array.isArray(data.errors)) {
console.error('Détails des erreurs de validation:', data.errors);
}
return;
}
} else if (error.request) {
console.error('Erreur de requête sans réponse:', error.request);
} else {
console.error('Erreur inconnue:', error.message);
}
}
content_copy
Create
Dans cette section, nous allons aborder l'opération de création Create et examiner comment créer une ressource en utilisant Axios.
Laravel
public function handleCrudPost(Request $request) {
$validatedData = $request->validate([
'nom' => 'required|string|regex:/^[a-zA-Z\s-]+$/|min:2|max:60',
'prenom' =>'required|string|regex:/^[a-zA-Z\s-]+$/|min:2|max:60',
]);
return response()->json([
'message' => 'Ressource créée.',
], 200);
}
content_copy
Flask
@app.route('/crud-post', methods=['POST'])
def submit_form():
data = request.get_json()
nom = data.get('nom', '').strip()
prenom = data.get('prenom', '').strip()
# Vérification des champs
if not (nom and prenom):
return jsonify({'message': 'Tous les champs sont obligatoires.'}), 400
nom_regex = r'^[a-zA-Z\s-]+$'
if not (re.match(nom_regex, nom) and re.match(nom_regex, prenom)):
return jsonify({'message': 'Champs invalides.'}), 400
return jsonify({'message': 'Formulaire soumis avec succès !'}), 200
Hapi Js
server.route({
method: 'POST',
path: '/handle-crud-post',
options: {
validate: {
payload: Joi.object({
nom: Joi.string().pattern(/^[a-zA-Z\s-]+$/).min(2).max(60).required(),
prenom: Joi.string().pattern(/^[a-zA-Z\s-]+$/).min(2).max(60).required()
}),
failAction: (request, h, err) => {
// Renvoie une réponse d'erreur en cas d'échec de la validation
return h.response({ message: err.details[0].message }).code(400).takeover();
}
}
},
handler: (request, h) => {
return h.response({
message: 'Ressource créée.'
}).code(200);
}
});
Formulaire HTML
Nous allons commencer par créer un formulaire avec deux champs :
// CSS
.bg-danger { background-color: rgb(221, 62, 62); }
.bg-success { background-color: #2dd288; }
<form @submit="handleForm">
// csrf
<div class="mb-3">
<label for="labelInputEmail" class="form-label">Nom</label>
<input type="text" class="form-control" v-model="nom" aria-describedby="nom">
</div>
<div class="mb-3">
<label for="labelInputEmail" class="form-label">Prénom</label>
<input type="text" class="form-control" v-model="prenom" aria-describedby="prenom">
</div>
<button class="btn btn-success" :disabled="!isFormValid">Envoyer les données</button>
</form>
<div v-if="showMessage" :class="['message-info', bgColor]">
{{ message }}
</div>
content_copy
Code Vue
Maintenant, nous allons écrire le code Vue pour gérer le bouton de validation, la liaison des champs et l'affichage des messages :
// Consts
const nomRegex = /^[a-zA-Z\s-]+$/;
// Variables
let nom = ref('');
let prenom = ref('');
let isFormValid = ref(false);
let message = ref('');
let error = ref('');
let showMessage = ref(false);
let bgColor = ref(null);
watchEffect(() => {
// Vérifie si tous les champs sont remplis
isFormValid.value = nomRegex.test(nom.value.trim()) &&
nomRegex.test(prenom.value.trim());
});
async function postRequest() {
const dataToSend = {
nom: nom.value,
prenom: prenom.value
};
try {
const response = await axios.post('crud-post', dataToSend);
return response;
} catch (err) {
throw err;
}
}
function resetForm() {
nom.value = '';
prenom.value = '';
}
function showMessageInfo(message_, backgroundColor) {
showMessage.value = true;
message.value = message_;
bgColor.value = backgroundColor;
setTimeout(() => {
showMessage.value = false;
}, 3000);
}
async function handleForm(event) {
event.preventDefault();
if (!isFormValid.value) { return; }
try {
const response = await postRequest();
const statusCode = response.status;
if (statusCode === 200) {
message.value = response.data.message;
showMessageInfo(message, 'bg-success');
resetForm();
} else {
message.value = response.data.message;
showMessageInfo(message, 'bg-danger');
}
} catch (err) {
console.error('Erreur lors de la requête API :', err);
message.value = 'Une erreur s'est produite : ' + err.message;
showMessageInfo(message, 'bg-danger');
}
}
return {
loading,
nom,
prenom,
isFormValid,
showMessage,
message,
bgColor,
handleForm,
}
content_copy
Read
Dans cette section, nous allons voir l'opération Read et comment lire des ressources avec Axios et Laravel.
Laravel
public function getInfo() {
// Liste des utilisateurs
$users = [
['id' => 1, 'name' => 'Mahmoud'],
['id' => 2, 'name' => 'Toto'],
['id' => 3, 'name' => 'Tata'],
['id' => 4, 'name' => 'Titi'],
];
return response()->json([
'users' => $users,
], 200);
}
content_copy
Flask
@app.route('/getInfo', methods=['GET'])
def get_info():
if request.method != 'GET':
return jsonify({"error": "Method Not Allowed"}), 405
# Liste des utilisateurs
users = [
{'id': 1, 'name': 'Mahmoud'},
{'id': 2, 'name': 'Puline'},
{'id': 3, 'name': 'Farid'},
{'id': 4, 'name': 'Gaya'},
]
return jsonify({'users': users}), 200
Hapi Js
server.route({
method: 'GET',
path: '/get-info',
handler: (request, h) => {
// Liste des utilisateurs
const users = [
{ id: 1, name: 'Mahmoud' },
{ id: 2, name: 'Toto' },
{ id: 3, name: 'Tata' },
{ id: 4, name: 'Titi' },
];
return h.response({
users: users
}).code(200);
}
});
Code HTML
<canvas ref="myChart"></canvas>
content_copy
Code Vue
Dans notre code Vue.js, nous allons récupérer les données du contrôleur avec une requête GET, puis créer un graphique avec Chart.js.
let ventes = ref(null);
let error = ref(null);
let myChart = ref(null);
// Requête Axios
async function getData() {
try {
const response = await axios.get('get-info');
ventes.value = response.data.ventes;
} catch (err) {
console.log('Erreur lors de la requête API :', err.message);
} finally {
initializeChart();
}
}
// Code du chart
function initializeChart() {
if (ventes.value === null) {
console.log("ERREUR : Aucune donnée.");
return;
}
const ctx = myChart.value.getContext('2d');
new Chart(ctx, {
type: 'bar',
data: {
// On extrait les mois ['Janvier', 'Février', 'Mars']
labels: ventes.value.map(vente => vente.mois),
datasets: [{
label: 'Ventes',
// On extrait les valeurs [140, 240, 350]
data: ventes.value.map(vente => vente.data),
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}
onMounted(async () => {
getData();
});
return {
loading,
ventes,
myChart,
}
content_copy
Update
Dans cette section, nous allons aborder l'opération de mise à jour Update et explorer comment mettre à jour une ressource en utilisant Axios.
Delete
Dans cette section, nous allons aborder l'opération de suppression Delete et étudier comment supprimer une ressource en utilisant Axios.