Réactivité sans framework : ce que JavaScript natif permet aujourd'hui
Vous souhaitez un comportement d’interface réactif — des changements d’état qui mettent automatiquement à jour le DOM — mais vous ne voulez pas embarquer 40 Ko de code de framework pour un simple widget. Bonne nouvelle : la réactivité en JavaScript vanilla est tout à fait réalisable avec des API stables dans les navigateurs depuis des années.
Cet article couvre les outils natifs disponibles fin 2025 pour construire des interfaces réactives : l’état réactif basé sur Proxy, EventTarget et CustomEvent pour le pub/sub, et les observateurs de navigateur pour les réactions conscientes du DOM. Vous découvrirez ce qui fonctionne aujourd’hui, ce qui arrive, et comment ces patterns correspondent aux mécanismes internes des frameworks.
Points clés à retenir
- Les objets Proxy interceptent les changements de propriétés et permettent des mises à jour automatiques du DOM sans dépendances de framework
- EventTarget et CustomEvent fournissent une couche pub/sub native pour la communication découplée entre composants
- Les observateurs de navigateur (MutationObserver, IntersectionObserver, ResizeObserver) gèrent la réactivité du DOM et de la mise en page
- La proposition TC39 Signals pourrait standardiser les primitives de réactivité, mais les patterns actuels Proxy + EventTarget obtiennent des résultats similaires dès aujourd’hui
Ce que signifie réellement la réactivité
La réactivité est une boucle simple : les changements d’état déclenchent des mises à jour de l’interface. Les frameworks automatisent cela avec des DOM virtuels, des compilateurs ou un suivi de dépendances granulaire. Mais les mécanismes sous-jacents reposent sur des fonctionnalités JavaScript que vous pouvez utiliser directement.
Le pattern de base :
- Stocker l’état dans une structure traçable
- Notifier les abonnés lorsque l’état change
- Mettre à jour uniquement le DOM concerné
Les API natives du navigateur gèrent chaque étape sans dépendances externes.
État réactif basé sur Proxy
L’objet Proxy intercepte l’accès et l’affectation de propriétés. Combiné avec Reflect, il constitue la fondation d’un état réactif basé sur proxy.
function createReactiveStore(initial, onChange) {
return new Proxy(initial, {
set(target, prop, value) {
const result = Reflect.set(target, prop, value)
onChange(prop, value)
return result
}
})
}
const state = createReactiveStore({ count: 0 }, (prop, value) => {
document.getElementById('count').textContent = value
})
state.count = 5 // Le DOM se met à jour automatiquement
Ce pattern ressemble à un « signal » — vous écrivez dans l’état, et les effets s’exécutent. Le système de réactivité de Vue 3 utilise Proxy en interne pour exactement cette raison.
Limitation : Les trappes Proxy se déclenchent uniquement sur les mutations appliquées à l’objet proxifié lui-même. Si les objets imbriqués ou les tableaux ne sont pas également enveloppés dans leurs propres proxies, les changements à l’intérieur (comme array.push()) ne seront pas suivis. De nombreux développeurs utilisent des mises à jour immuables (par exemple, state.items = [...state.items, newItem]) pour garantir que les mises à jour se déclenchent.
EventTarget et CustomEvent comme couche Pub/Sub
Pour la communication découplée entre composants, EventTarget fournit un mécanisme pub/sub natif. N’importe quel objet peut devenir un émetteur d’événements.
const bus = new EventTarget()
// S'abonner
bus.addEventListener('state-change', (e) => {
console.log('Nouvelle valeur:', e.detail)
})
// Publier
bus.dispatchEvent(new CustomEvent('state-change', {
detail: { count: 10 }
}))
Ce pattern alimente une interface réactive avec des API natives du navigateur. Les composants s’abonnent aux événements, réagissent aux changements et restent découplés. Contrairement aux implémentations pub/sub personnalisées, EventTarget s’intègre avec les DevTools du navigateur et suit la sémantique standard des événements.
Discover how at OpenReplay.com.
Observateurs de navigateur pour la réactivité du DOM
Lorsque vous devez réagir aux changements du DOM ou de la mise en page — pas seulement à l’état — les observateurs de navigateur comblent le vide.
MutationObserver surveille les modifications du DOM :
const observer = new MutationObserver((mutations) => {
mutations.forEach(m => console.log('DOM modifié:', m))
})
observer.observe(document.body, { childList: true, subtree: true })
IntersectionObserver suit la visibilité des éléments — utile pour le chargement différé ou l’analytique.
ResizeObserver répond aux changements de taille des éléments sans polling.
Ces API sont stables depuis longtemps et sont sûres pour la production. Elles complètent la réactivité pilotée par l’état en gérant les cas où des facteurs externes modifient le DOM.
La proposition TC39 Signals : ce qui arrive
Il y a un intérêt croissant pour standardiser les primitives de réactivité. La proposition TC39 Signals vise à définir un modèle commun que les frameworks pourraient partager.
Important : En 2025, il s’agit encore d’une proposition — pas d’une fonctionnalité JavaScript livrée. Des frameworks comme Solid, Angular et Preact ont adopté des patterns de type signal, influençant la conception de la proposition. Mais vous ne pouvez pas utiliser de « signaux natifs » dans les navigateurs aujourd’hui.
Les patterns Proxy + EventTarget ci-dessus atteignent des objectifs similaires. Si les signaux se standardisent, la migration devrait être simple puisque le modèle mental s’aligne.
Choisir le bon pattern
| Pattern | Idéal pour | Compromis |
|---|---|---|
| Proxy | État local de composant | Ne suit que les changements sur l’objet proxifié, sauf si les valeurs imbriquées sont également proxifiées |
| EventTarget | Messagerie inter-composants | Câblage manuel |
| MutationObserver | Réagir aux changements externes du DOM | Surcharge de performance |
Pour les petites applications et widgets, combiner l’état basé sur Proxy avec EventTarget couvre la plupart des besoins d’interface réactive sans surcharge de framework.
Conclusion
La réactivité sans framework est pratique aujourd’hui. Proxy gère le suivi d’état, EventTarget fournit le pub/sub, et les observateurs de navigateur réagissent aux changements du DOM. Ces API sont stables, bien documentées et se composent en un noyau réactif léger.
Vous n’avez pas besoin d’un framework pour obtenir une réactivité granulaire. Vous devez comprendre les primitives sur lesquelles les frameworks sont construits — et maintenant c’est le cas.
FAQ
Les trappes Proxy se déclenchent uniquement sur l'affectation directe de propriétés à l'objet proxifié. Pour les objets imbriqués, vous devez soit envelopper récursivement chaque objet imbriqué dans son propre Proxy, soit remplacer toute la structure imbriquée lors des modifications. La plupart des développeurs optent pour des patterns de mise à jour immuables comme le spread pour créer de nouvelles références.
EventTarget est une API native du navigateur qui s'intègre avec les DevTools et suit la sémantique de dispatch standard. Le bubbling et la capture complets s'appliquent uniquement lorsque la cible de l'événement fait partie de l'arbre DOM. Les bibliothèques personnalisées peuvent offrir des fonctionnalités supplémentaires comme des écouteurs avec wildcards ou des abonnements à usage unique, mais EventTarget ne nécessite aucune dépendance et fonctionne de manière cohérente sur tous les navigateurs modernes.
Utilisez MutationObserver lorsque vous devez réagir aux changements du DOM effectués par du code externe, des scripts tiers ou des extensions de navigateur. Proxy suit les changements d'état JavaScript que vous contrôlez. MutationObserver surveille l'arbre DOM réel quelle que soit la cause du changement. Ils servent des objectifs différents et fonctionnent souvent ensemble.
La proposition Signals vise à standardiser les primitives de réactivité que les frameworks peuvent partager, pas à remplacer les API existantes. Proxy et EventTarget resteront des approches valides. Si Signals est livré, ils compléteront probablement ces patterns en fournissant une interface standard pour le suivi de dépendances granulaire entre différentes bibliothèques.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.