Génie civil & structural
Création d'un gestionnaire de signets Javascript avec la persistance du stockage local
Table of Contents
Comprendre les bases
Construire un gestionnaire de signets avec JavaScript et l'API de stockage Web est un excellent projet pour maîtriser les concepts front-end fondamentaux. À son cœur, l'application doit gérer trois opérations principales: create, read, et delete — un modèle CRUD classique, moins les mises à jour pour le moment. Les données vivent dans le navigateur localStorage, permettant aux signets de persister à travers les sessions sans serveur.
Avant d'écrire une seule ligne de code, solidifiez votre compréhension des piliers suivants:
- L'API DOM:[ Vous allez interroger des éléments, écouter les événements et manipuler l'arborescence de documents pour afficher dynamiquement les signets.
- localStorage: Ce magasin de valeurs-clés conserve les données même après la fermeture du navigateur. Il ne prend en charge que les chaînes, de sorte que les objets doivent être sérialisés avec et désérialisés avec .
- Programmation animée par un événement:[ Les formulaires émettent des événements ; suppriment les boutons feu événements. La maîtrise est non négociable.
- ]][[FLT:]][[FLT:]][[FLT:]]][[FLT:]][[FLT:]][[FLT:]][[FLT:]][[FLT:]][FLT:][FLT:]][[FLT:]][FLT:][FLT:]][[FLT:]][FLT]][FLT][FLT]][FLT][FLT]][FLT][FLT]][FLT]][[FLT]][[FLT]]
Construire le gestionnaire de signets de base
Structure HTML
Commencez par un squelette HTML sémantique minimal. Le formulaire recueille le nom et l'URL du signet ; une liste non ordonnée rend les signets stockés.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bookmark Manager</title>
</head>
<body>
<h1>My Bookmarks</h1>
<form id="bookmarkForm">
<label for="name">Name</label>
<input type="text" id="name" required />
<label for="url">URL</label>
<input type="url" id="url" required />
<button type="submit">Add Bookmark</button>
</form>
<ul id="bookmarkList"></ul>
<script src="app.js" defer></script>
</body>
</html>
Notez l'attribut sur la balise de script – il garantit que le DOM est entièrement analysé avant que le script ne soit lancé, éliminant ainsi la nécessité d'un wrapper dans les configurations modernes.
Styling pour la facilité d'emploi (facultatif mais recommandé)
Bien que CSS ne soit pas le focus, une interface propre améliore l'expérience utilisateur. Ajoutez une simple feuille de style pour espacer le formulaire, donnez un look cohérent aux boutons et stylez les éléments de la liste des signets avec des effets de vol stationnaire. Un style en ligne minimal peut également être injecté via JavaScript, mais un séparé est préféré pour la maintenance.
<!-- inside <head> -->
<link rel="stylesheet" href="style.css" />
Dans , utilisez la boîte flex pour la mise en page du formulaire, une largeur maximale pour le conteneur et des commentaires visuels distincts pour supprimer les boutons pour éviter les clics accidentels.
JavaScript Logic – Le cœur de l'application
Toutes les fonctions de persistance et d'interactivité sont réparties en .
Initialisation des données
Nous avons besoin d'une variable centrale qui tient la liste courante des signets. Elle doit être initialisée à partir de ou revenir à un tableau vide.
let bookmarks = [];
function loadBookmarks() {
const stored = localStorage.getItem('bookmarks');
if (stored) {
bookmarks = JSON.parse(stored);
} else {
bookmarks = [];
}
}
function saveBookmarks() {
localStorage.setItem('bookmarks', JSON.stringify(bookmarks));
}
loadBookmarks();
La fonction est appelée chaque fois que le tableau change — après avoir ajouté, modifié ou supprimé un signet. Cela garantit que le stockage est toujours synchronisé avec le tableau in-memory.
Affichage des signets
Rendu la liste des signets signifie qu'il faut passer par le tableau et créer des éléments de liste avec une balise d'ancrage et un bouton de suppression.
function renderBookmarks() {
const list = document.getElementById('bookmarkList');
list.innerHTML = ''; // clear existing entries
bookmarks.forEach(function(bookmark, index) {
const li = document.createElement('li');
li.dataset.index = index;
const link = document.createElement('a');
link.href = bookmark.url;
link.textContent = bookmark.name;
link.target = '_blank';
link.rel = 'noopener noreferrer';
const deleteBtn = document.createElement('button');
deleteBtn.textContent = 'Delete';
deleteBtn.addEventListener('click', function() {
deleteBookmark(index);
});
li.appendChild(link);
li.appendChild(deleteBtn);
list.appendChild(li);
});
}
Utiliser au lieu d'innerHTML évite les vulnérabilités XSS lorsque les noms de signets contiennent HTML. Le bouton de suppression utilise une fermeture pour capturer l'index de signets.
Ajout d'un signet
Écoutez l'événement form-s , empêchez le rechargement de la page par défaut, créez un objet signet, poussez-le vers le tableau, persistez et renvoyez.
document.getElementById('bookmarkForm').addEventListener('submit', function(e) {
e.preventDefault();
const nameInput = document.getElementById('name');
const urlInput = document.getElementById('url');
const newBookmark = {
name: nameInput.value.trim(),
url: urlInput.value.trim()
};
// Basic validation: ensure URL starts with http/https
if (!newBookmark.url.startsWith('http://') && !newBookmark.url.startsWith('https://')) {
newBookmark.url = 'https://' + newBookmark.url;
}
bookmarks.push(newBookmark);
saveBookmarks();
renderBookmarks();
// Reset form
nameInput.value = '';
urlInput.value = '';
nameInput.focus();
});
Cette approche est simple. Pour la production, vous pouvez valider le format URL en utilisant constructeur ou un regex.
Suppression d'un signet
Suppression supprime l'élément à l'index donné et met à jour le stockage et le DOM.
function deleteBookmark(index) {
bookmarks.splice(index, 1);
saveBookmarks();
renderBookmarks();
}
Si vous préférez l'immutabilité, vous pouvez utiliser et réaffecter , mais pour un petit projet comme celui-ci, est clair et performant.
Améliorer la demande
Une fois que le CRUD de base fonctionne, considérez ces améliorations pour transformer un prototype en un outil robuste.
Modifier les signets
Remplacer le nom/lien statique par un mode d'édition en ligne. Lorsque l'utilisateur clique sur un bouton d'édition, échangez la balise d'ancrage avec les champs d'entrée préremplis avec les valeurs actuelles.
Conseil d'implémentation : ajouter une fonction qui crée des entrées modifiables. Utilisez event delegation sur la liste pour gérer les sauvegardes d'édition sans joindre plusieurs auditeurs.
Catégorisation avec les étiquettes
Ajoutez une propriété optionnelle à chaque objet de signet (p. ex. ). Ensuite, prolongez l'interface utilisateur avec une entrée de filtre qui masque les éléments de liste dont les balises ne correspondent pas. Vous pouvez stocker les balises comme une chaîne séparée par des virgules à l'intérieur du formulaire et les diviser en tableau.
Importation et exportation
Autoriser les utilisateurs à sauvegarder ou transférer des signets. Utilisez un ou un téléchargement de fichier. Exporter sérialise dans une chaîne JSON et déclenche un téléchargement via et . Importer lit le JSON et fusionne avec des signets existants.
function exportBookmarks() {
const data = JSON.stringify(bookmarks, null, 2);
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'bookmarks.json';
a.click();
URL.revokeObjectURL(url);
}
Recherche et filtre
Ajoutez une entrée au-dessus de la liste des signets. Sur chaque événement , filtrez le tableau par nom (ou URL) et appelez une variante de qui affiche seulement les correspondances. Pour éviter de perdre la liste originale, stockez une copie filtrée ou utilisez un paramètre calculé.
Test et compatibilité du navigateur
localStorage est pris en charge dans tous les navigateurs modernes, mais les anciennes versions d'Internet Explorer (IE 8+) avaient une API différente. Si vous devez supporter les environnements hérités, tester avec des polyfills ou revenir aux cookies. Aujourd'hui Chrome, Firefox, Safari, Edge (à la fois Chrome et legacy) poignée et sans problèmes.
Lors de l'essai, vérifier:
- Les données survivent à la page rafraîchit et le navigateur redémarre.
- Suppression d'un signet met à jour l'interface utilisateur et le stockage.
- Les caractères spéciaux dans les noms de signets (quotes, ampersands) sont rendus correctement.
- Les URL avec et sans sont normalisées.
Utilisez ] > Application > Storage > Local Storage pour inspecter manuellement les données enregistrées.
Pour les tests automatisés, envisagez d'utiliser Cypress[ ou Playwright[ pour simuler les flux de travail de l'utilisateur — remplir le formulaire, ajouter, supprimer, recharger — et affirmer que la liste persiste.
Conclusion
Ce projet démontre comment quelques dizaines de lignes de JavaScript vanillé peuvent créer une application web entièrement fonctionnelle et persistante. Vous avez appris à exploiter l'API localStorage[ pour la persistance des données, la délégation d'événement[ pour des mises à jour efficaces de l'interface utilisateur, et les opérations de CRUD[ sans backend. Le modèle que vous avez appliqué — initialiser l'état de stockage, muter l'état par des fonctions, et re- rendre le DOM — est la base de nombreux cadres front-end modernes comme Réact ou Vue.
Pour approfondir votre compréhension, explorez la documentation MDN sur localStorage et lisez management d'événements dans le DOM. Pour une gestion d'état plus avancée, consultez IndexedDB pour les ensembles de données plus importants ou les travailleurs de service[ pour les premières expériences hors ligne.