logo hsb.horse
← Retour à l’index des snippets

Snippets

Mise en place idempotente d'un observateur DOM via dataset

Un pattern simple utilisant les attributs data pour éviter les doublons d'enregistrement de MutationObserver. Aucun registre global requis, très portable.

Publié: Mis à jour:

Lorsque MutationObserver est configuré plusieurs fois, des observateurs en double peuvent être enregistrés sur le même élément. Gérer cela avec un Set ou une Map global est possible, mais écrire un flag d’observation dans dataset est léger et facile à porter.

Code

const OBSERVE_ID_KEY = 'observeId'
const isElementObserved = <T extends HTMLElement = HTMLElement>(
ele: T
) => Object.hasOwn(ele.dataset, OBSERVE_ID_KEY)
const setObserverId =
(id: string) =>
<T extends HTMLElement = HTMLElement>(ele: T): T => {
ele.dataset[OBSERVE_ID_KEY] = id
return ele
}
export const observeElement = (
observeId: string,
element: HTMLElement | string,
observerCallback: MutationCallback,
options: MutationObserverInit = { childList: true }
) => {
const observedElement =
element instanceof HTMLElement
? element
: document.querySelector<HTMLElement>(element)
if (observedElement && !isElementObserved(observedElement)) {
const observer = new MutationObserver(observerCallback)
observer.observe(observedElement, options)
setObserverId(observeId)(observedElement)
return observer
}
}

Utilisation

// Accepte un sélecteur CSS ou un HTMLElement
observeElement(
'my-list-observer',
'#item-list',
(mutations) => {
for (const mutation of mutations) {
console.log('Changement détecté :', mutation.type)
}
}
)
// Appeler à nouveau sur le même élément ne crée pas de doublon
observeElement('my-list-observer', '#item-list', callback)

Fonctionnement

  1. Object.hasOwn(ele.dataset, OBSERVE_ID_KEY) vérifie la présence de l’attribut data-observe-id
  2. Seulement si non enregistré, un MutationObserver est créé et observe() est appelé
  3. Après le démarrage de l’observation, le flag est écrit via ele.dataset[OBSERVE_ID_KEY] = id
  4. Lors des appels suivants, isElementObserved renvoie true et rien ne se passe

Les valeurs de dataset étant écrites directement dans l’attribut HTML data-*, elles sont visibles dans les DevTools.

Avantages

  • Pas de registre global : L’état est stocké dans l’élément lui-même, éliminant le besoin de gérer une Map ou un Set séparé
  • Très portable : Aucune dépendance à un framework ; fonctionne dans n’importe quel environnement
  • Facile à déboguer : Les valeurs des attributs peuvent être inspectées directement dans les DevTools

Points d’attention

Lorsqu’un élément est supprimé du DOM, ses informations dataset sont également perdues. Si le même élément est réinséré, un observateur sera à nouveau enregistré. De plus, pour arrêter un observateur, il faut appeler observer.disconnect() séparément.