Pourquoi utiliser les Web Components en JavaScript ?
L’écosystème JavaScript évolue rapidement, mais les standards du web restent. Créer des composants réutilisables avec les Web Components permet de développer des interfaces agnostiques, compatibles avec n’importe quel projet. Cette approche repose sur trois technologies natives du navigateur : les Custom Elements, le Shadow DOM et les balises HTML Templates.
Définir un Custom Element de base
La première étape pour créer un composant réutilisable consiste à définir une classe JavaScript qui hérite de l’interface standard. Nous allons créer un composant de carte utilisateur basique.
class UserCard extends HTMLElement {
constructor() {
super();
this.innerHTML = `<div class="card">Utilisateur standard</div>`;
}
}
customElements.define('user-card', UserCard);Une fois défini, ce composant peut être utilisé directement dans votre code HTML avec la balise personnalisée que nous avons déclarée.
<user-card></user-card>Isoler les styles avec le Shadow DOM
Le véritable pouvoir des Web Components réside dans l’encapsulation. Le Shadow DOM permet de s’assurer que le CSS de votre composant n’affectera pas le reste de la page, et inversement.
class UserCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
.card {
border: 1px solid #ccc;
padding: 1rem;
border-radius: 8px;
background: #f9f9f9;
}
</style>
<div class="card">
<h3>Profil Utilisateur</h3>
<p>Détails de l'utilisateur ici.</p>
</div>
`;
}
}
customElements.define('user-card', UserCard);Rendre le composant dynamique avec les attributs
Pour que notre création soit réellement un composant réutilisable, il doit pouvoir accepter des données externes via des attributs HTML.
See the Pen Creer un template html by upstart.re (@gav974) on CodePen.
Le cycle de vie du composant
Les Web Components disposent de méthodes spécifiques appelées lors des différentes étapes de leur cycle de vie. La méthode la plus utile pour la réactivité est l’observation des attributs.
class UserCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
static get observedAttributes() {
return ['username', 'role'];
}
connectedCallback() {
this.render();
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
this.render();
}
}
render() {
const username = this.getAttribute('username') || 'Anonyme';
const role = this.getAttribute('role') || 'Visiteur';
this.shadowRoot.innerHTML = `
<style>
.card { border: 2px solid #007bff; padding: 15px; }
.role { color: #666; font-style: italic; }
</style>
<div class="card">
<h3>${username}</h3>
<p class="role">${role}</p>
</div>
`;
}
}
customElements.define('user-card', UserCard);Utiliser les Templates et les Slots
Lorsque le contenu HTML devient complexe, il est préférable d’utiliser la balise template et le mécanisme de slots pour injecter du contenu depuis l’extérieur du composant.
<template id="card-template">
<style>
.wrapper { background: #fff; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
</style>
<div class="wrapper">
<h3><slot name="title">Titre par défaut</slot></h3>
<slot>Contenu par défaut</slot>
</div>
</template>Ce système de slots offre une flexibilité maximale, similaire à la composition de composants que l’on retrouve dans les frameworks modernes.
Vérification et bonnes pratiques
Avant de déployer vos Web Components en production, prenez en compte ces quelques règles essentielles pour garantir leur fiabilité.
| Pratique | Recommandation |
|---|---|
| Nommage | Utilisez toujours un tiret dans le nom du Custom Element (ex: my-element). |
| Shadow DOM | Privilégiez le mode open pour faciliter le débogage. |
| Performances | Évitez les opérations lourdes dans le constructor, utilisez connectedCallback. |


