25 min JavaScript — modularité, performance et API navigateur Gratuit
Objectif : Enregistrer et restaurer l’état des tâches dans le navigateur en gérant les erreurs de lecture.
Si vous rechargez la page, les tâches conservées uniquement en mémoire disparaissent. Vous allez enregistrer leur liste dans le navigateur et la restaurer au prochain démarrage, sans laisser une donnée corrompue bloquer l’application.
Dans les leçons précédentes, vous avez séparé l’état, les transitions et les interactions avec le DOM. Ici, `persistance.js` joue le rôle d’adaptateur de stockage : il lit et écrit les tâches, tandis que `main.js` décide quand appeler ces opérations.
Enregistrer et relire une liste de tâches
`localStorage` conserve des chaînes dans le navigateur, pour une origine donnée, même après la fermeture de la page. Vous convertissez donc la liste en texte avec `JSON.stringify` avant l’écriture, puis vous la reconstruisez avec `JSON.parse` à la lecture. Une clé constante évite de disperser le nom de l’entrée dans le code.
js/persistance.jsJavaScript
const CLE_STOCKAGE = "gestionnaire-taches-v1";
export function chargerTaches() {
try {
const contenu = localStorage.getItem(CLE_STOCKAGE);
if (contenu === null) {
return [];
}
const taches = JSON.parse(contenu);
if (!Array.isArray(taches)) {
throw new TypeError("Les données enregistrées ne sont pas une liste.");
}
return taches.filter(function (tache) {
return tache !== null
&& typeof tache === "object"
&& typeof tache.id === "string"
&& typeof tache.libelle === "string"
&& typeof tache.terminee === "boolean";
});
} catch (erreur) {
console.warn("Les tâches enregistrées n’ont pas pu être lues.", erreur);
return [];
}
}
export function enregistrerTaches(taches) {
try {
localStorage.setItem(CLE_STOCKAGE, JSON.stringify(taches));
return true;
} catch (erreur) {
console.warn("Les tâches n’ont pas pu être enregistrées.", erreur);
return false;
}
}
Aperçu du rendu
Chargement de l'aperçu…
const CLE_STOCKAGE = "gestionnaire-taches-v1";
export function chargerTaches() {
try {
const contenu = localStorage.getItem(CLE_STOCKAGE);
if (contenu === null) {
return [];
}
const taches = JSON.parse(contenu);
if (!Array.isArray(taches)) {
throw new TypeError("Les données enregistrées ne sont pas une liste.");
}
return taches.filter(function (tache) {
return tache !== null
&& typeof tache === "object"
&& typeof tache.id === "string"
&& typeof tache.libelle === "string"
&& typeof tache.terminee === "boolean";
});
} catch (erreur) {
console.warn("Les tâches enregistrées n’ont pas pu être lues.", erreur);
return [];
}
}
export function enregistrerTaches(taches) {
try {
localStorage.setItem(CLE_STOCKAGE, JSON.stringify(taches));
return true;
} catch (erreur) {
console.warn("Les tâches n’ont pas pu être enregistrées.", erreur);
return false;
}
}<style>:root{--taches-couleur-fond:#f4f6f8;--taches-couleur-surface:#ffffff;--taches-couleur-texte:#202833;--taches-couleur-accent:#176b55;--taches-couleur-bordure:#d4dbe0;--taches-espace:1rem;--taches-espace-large:2rem;--taches-rayon:0.5rem;--taches-police:system-ui, sans-serif;--taches-taille-texte:1rem;}</style><!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#f4f6f8">
<title>Gestionnaire de tâches</title>
<link rel="stylesheet" href="style.css">
<script type="module" src="js/main.js"></script>
</head>
<body>
<main class="taches" aria-labelledby="titre-taches">
<header class="taches__entete">
<h1 id="titre-taches">Gestionnaire de tâches</h1>
<p>Organisez vos tâches et suivez votre progression.</p>
</header>
<section class="taches__progression" aria-labelledby="titre-progression" data-progression>
<h2 id="titre-progression">Progression</h2>
<p><span data-terminees>0</span> tâche(s) terminée(s) sur <span data-total>0</span></p>
<progress class="taches__barre" data-barre value="0" max="0" aria-label="Progression des tâches">0%</progress>
</section>
<form class="taches__formulaire" data-formulaire>
<label for="nouvelle-tache">Nouvelle tâche</label>
<input class="taches__champ" id="nouvelle-tache" name="tache" type="text" required maxlength="200" autocomplete="off">
<button type="submit">Ajouter</button>
</form>
<section aria-labelledby="titre-liste">
<h2 id="titre-liste">Mes tâches</h2>
<ul class="taches__liste" data-liste aria-live="polite"></ul>
</section>
<footer class="taches__commandes">
<button class="taches__copier" type="button" data-copier>Copier le résumé</button>
</footer>
<p class="taches__message" data-message role="status" aria-live="polite"></p>
</main>
</body>
</html>
La lecture peut échouer si le navigateur refuse l’accès au stockage ou si le texte enregistré n’est pas du JSON valide. Le bloc `try...catch` couvre ces erreurs ; le contrôle de forme écarte aussi les éléments qui ne respectent pas le modèle des tâches. L’application démarre alors avec une liste vide au lieu de s’arrêter.
Brancher le stockage au cycle des actions
Au démarrage, `main.js` construit l’état à partir des tâches restaurées. Après chaque action, il applique la transition pure, puis enregistre la nouvelle liste. Pour garder cette étape exécutable avec le squelette actuel, `dom.js` expose toujours les mêmes actions d’ajout, de bascule et de suppression.
L’appel à `enregistrerTaches` intervient après chaque transition, y compris quand l’action ne change pas la liste. L’écriture renvoie un booléen que vous pourrez exploiter pour afficher un message dans une prochaine étape ; pour l’instant, l’erreur est signalée dans la console et ne bloque pas les interactions.
Page de référence
Le script utilise les points d’ancrage prévus par le HTML de référence. Conservez la même page et la même feuille `style.css` ; aucune classe ni aucun style inline n’est ajouté pour la persistance.
Servez la page via un serveur local et ajoutez une tâche. Le stockage Web n’est pas fiable à tester en ouvrant simplement le fichier avec `file://`.
Dans les outils de développement, ouvrez le stockage local de l’origine et vérifiez l’entrée `gestionnaire-taches-v1`. Sa valeur est une chaîne JSON contenant les tâches.
Rechargez la page : l’état est reconstruit depuis cette entrée. Pour tester une donnée illisible, remplacez temporairement sa valeur par `{`, puis rechargez ; `chargerTaches` renvoie `[]` et signale l’erreur dans la console.
À retenir
`localStorage` conserve des chaînes entre les visites de la page pour une même origine.
`JSON.stringify` prépare les données à l’écriture ; `JSON.parse` les reconstruit à la lecture.
Encadrez la lecture et l’écriture par une gestion d’erreurs : le stockage peut être refusé ou contenir des données mal formées.
Validez la forme des données restaurées et fournissez un état de repli exploitable.
La prochaine leçon utilisera `IntersectionObserver` pour déclencher une opération en fonction de la visibilité d’un élément.
Envie d'aller plus loin ?
Les cours Enovatic sont gratuits et le resteront. Si vous cherchez un accompagnement
encadré, nos formations professionnelles sont animées par les mêmes formateurs.