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 HTMLElementobserveElement( '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 duplicadoobserveElement('my-list-observer', '#item-list', callback)Como Funciona
Object.hasOwn(ele.dataset, OBSERVE_ID_KEY)verifica a presença do atributodata-observe-id- Somente se não registrado, um
MutationObserveré criado eobserve()é chamado - Após o início da observação, o flag é gravado via
ele.dataset[OBSERVE_ID_KEY] = id - Em chamadas subsequentes,
isElementObservedretornatruee 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
MapouSetseparado - 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.
hsb.horse