Como o JavaScript funciona: rastreando as alterações no DOM usando o MutationObserver

Este é o post #10 da série dedicada a explorar JavaScript e seus componentes de construção. No processo de identificação e descrição dos elementos centrais, também compartilhamos algumas regras práticas que usamos ao criar o SessionStack , um aplicativo JavaScript que precisa ser robusto e altamente eficiente para ajudar os usuários a ver e reproduzir seus defeitos do aplicativo da Web em tempo real.

Abaixo estão os posts dessa série publicados até o momento

Os aplicativos da web estão ficando cada vez mais pesados ​​no lado do cliente, devido a vários motivos, como a necessidade de uma interface do usuário mais rica para acomodar o que aplicativos mais complexos têm a oferecer, cálculos em tempo real e assim por diante.

O aumento da complexidade torna mais difícil saber o estado exato da interface do usuário a cada momento durante o ciclo de vida do seu aplicativo da web.

Isso fica ainda mais difícil se você está criando algum tipo de framework ou apenas uma biblioteca, por exemplo, que precisa reagir e executar certas ações que dependem do DOM.

Visão geral

O MutationObserver é uma API da Web fornecida por navegadores modernos para detectar alterações no DOM. Com essa API, é possível ouvir os nós recém-adicionados ou removidos, as alterações de atributos ou as alterações no conteúdo de texto dos nós de texto.

Por que você gostaria de fazer isso?

Existem alguns casos em que a API do MutationObserver pode ser realmente útil. Por exemplo:

  • Você deseja notificar o visitante do seu aplicativo da Web de que alguma alteração ocorreu na página em que ele está atualmente.
  • Você está trabalhando em uma nova estrutura JavaScript sofisticada que carrega dinamicamente módulos JavaScript com base em como o DOM é alterado.
  • Você pode estar trabalhando em um editor WYSIWYG, tentando implementar a funcionalidade desfazer/refazer. Aproveitando a API do MutationObserver, você sabe a qualquer momento quais alterações foram feitas, para que você possa desfazê-las facilmente.

Estes são apenas alguns exemplos de como o MutationObserver pode ser útil.

Como usar o MutationObserver

Implementar o MutationObserver no seu aplicativo é bastante fácil. Você precisa criar uma instância do MutationObserver passando uma função que seria chamada toda vez que uma mutação ocorresse. O primeiro argumento da função é uma coleção de todas as mutações que ocorreram em um único lote. Cada mutação fornece informações sobre seu tipo e as mudanças que ocorreram.

O objeto criado possui três métodos:

  • observe - começa a ouvir as alterações. Leva dois argumentos - o nó DOM que você deseja observar e um objeto de configuração
  • disconnect - para de escutar alterações
  • takeRecords - retorna o último lote de alterações antes que o retorno de chamada seja acionado.

O snippet a seguir mostra como começar a observar:

Agora, digamos que você tenha uma div muito simples no DOM:

Usando jQuery, você pode remover o atributo class dessa div:

Conforme começamos a observar, depois de chamarmos mutationObserver.observe(...) , vamos ver um log no console do respectivo MutationRecord :

Esta é a mutação causada pela remoção do atributo de class .

E, finalmente, para parar de observar o DOM após o término do trabalho, você pode fazer o seguinte:

Hoje em dia, o MutationObserver é amplamente suportado:

Alternativas

O MutationObserver, no entanto, nem sempre esteve por aí. Então, a que os desenvolvedores recorreram antes do surgimento do MutationObserver?

Existem algumas outras opções disponíveis:

  • Polling
  • MutationEvents
  • Animações CSS

Polling

A maneira mais simples e menos sofisticada era a pesquisa. Usando o navegador setInterval WebAPI, você pode configurar uma tarefa que verificaria periodicamente se ocorreram alterações. Naturalmente, esse método degrada significativamente o desempenho do aplicativo / website da web.

MutationEvents

No ano de 2000, a API MutationEvents foi introduzida. Embora seja útil, os eventos de mutação são acionados em todas as alterações no DOM, o que novamente causa problemas de desempenho. Atualmente, a API MutationEvents foi preterida e, em breve, os navegadores modernos deixarão de oferecer suporte completo.

Este é o suporte do navegador para MutationEvents :

Animações CSS

Uma alternativa um tanto estranha é aquela que se baseia em animações CSS. Pode parecer um pouco confuso. Basicamente, a ideia é criar uma animação que seria acionada quando um elemento fosse adicionado ao DOM. No momento em que a animação começa, o evento animationstart será acionado: se você tiver anexado um manipulador de eventos a esse evento, saberá exatamente quando o elemento foi adicionado ao DOM. O período de tempo de execução da animação deve ser tão pequeno que seja praticamente invisível para o usuário.

Primeiro, precisamos de um elemento pai, dentro do qual gostaríamos de ouvir as inserções de nó:

Para obter um identificador na inserção de nós, precisamos configurar uma série de animações de quadros-chave que serão iniciadas quando o nó for inserido:

Com os keyframes criados, a animação precisa ser aplicada nos elementos que você gostaria de ouvir. Observe as pequenas durações — elas estão relaxando a pegada de animação no navegador:

Isso adiciona a animação a todos os nós filhos do container-element. Quando a animação termina, o evento de inserção será acionado.

Precisamos de uma função JavaScript que funcionará como o ouvinte do evento. Dentro da função, a verificação inicial de event.animationName deve ser feita para garantir que seja a animação desejada.

Agora é hora de adicionar o ouvinte de evento ao pai:

Este é o suporte do navegador para animações CSS:

MutationObserver oferece várias vantagens sobre as soluções acima mencionadas. Em essência, ele cobre todas as alterações possíveis que podem ocorrer no DOM e é muito mais otimizado, pois dispara as alterações nos lotes. Além disso, o MutationObserver é suportado por todos os principais navegadores modernos, junto com alguns polyfills que usam o MutationEvents sob o capô.

MutationObserver ocupa uma posição central na biblioteca do SessionStack .

Depois de integrar a biblioteca do SessionStack no seu aplicativo da web, ele começa a coletar dados como alterações do DOM, solicitações de rede, exceções, mensagens de depuração etc. e os envia para nossos servidores. O SessionStack usa esses dados para recriar tudo o que aconteceu com seus usuários e mostre os problemas de seus produtos da mesma forma que eles aconteceram com seus usuários. Muitos usuários acham que o SessionStack grava um vídeo real — isso não acontece. Gravar um vídeo real é muito pesado, enquanto a pequena quantidade de dados que coletamos é muito leve e não afeta o desempenho do UX e do seu aplicativo da web.

Existe um plano gratuito se você quiser experimentar o SessionStack .

Recursos

Este é um artigo traduzido com a autorização do autor. O artigo original pode ser lido em https://blog.sessionstack.com/how-javascript-works-tracking-changes-in-the-dom-using-mutationobserver-86adc7446401

Autor do post original — Alexander Zlatkov— Co-founder & CEO @SessionStack