logo hsb.horse
← Voltar para o índice de snippets

Snippets

Configuração idempotente de observador DOM via dataset

Um padrão simples usando atributos data para evitar registros duplicados de MutationObserver. Sem necessidade de registro global, altamente portável.

Publicado: Atualizado:

Quando MutationObserver é configurado várias vezes, observadores duplicados podem ser registrados no mesmo elemento. Gerenciar isso com um Set ou Map global é uma opção, mas escrever um flag de observação no dataset é leve e fácil de portar.

Código

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
}
}

Uso

// Aceita tanto uma string seletora quanto um HTMLElement
observeElement(
'my-list-observer',
'#item-list',
(mutations) => {
for (const mutation of mutations) {
console.log('Mudança detectada:', mutation.type)
}
}
)
// Chamar novamente no mesmo elemento não registra um observador duplicado
observeElement('my-list-observer', '#item-list', callback)

Como Funciona

  1. Object.hasOwn(ele.dataset, OBSERVE_ID_KEY) verifica a presença do atributo data-observe-id
  2. Somente se não registrado, um MutationObserver é criado e observe() é chamado
  3. Após o início da observação, o flag é gravado via ele.dataset[OBSERVE_ID_KEY] = id
  4. Em chamadas subsequentes, isElementObserved retorna true e nada acontece

Como os valores de dataset são gravados diretamente no atributo HTML data-*, eles são visíveis no DevTools.

Benefícios

  • Sem registro global: O estado é armazenado no próprio elemento, eliminando a necessidade de gerenciar um Map ou Set separado
  • Altamente portável: Sem dependências de framework; funciona em qualquer ambiente
  • Fácil de depurar: Os valores dos atributos podem ser inspecionados diretamente no DevTools

Cuidados

Quando um elemento é removido do DOM, suas informações de dataset também são perdidas. Se o mesmo elemento for reinserido, um observador será registrado novamente. Além disso, para parar um observador, é necessário chamar observer.disconnect() separadamente.