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
- Uma visão geral do mecanismo, o tempo de execução e a pilha de chamadas
- Dentro do motor V8 do Google + 5 dicas sobre como escrever código otimizado
- Gerenciamento de memória + como lidar com 4 vazamentos comuns de memória
- O Event loop e o surgimento da programação assíncrona + 5 maneiras de codificar melhor com async/await
- Como o JavaScript funciona: Aprofundando em WebSockets e HTTP/2 com SSE + como escolher o caminho certo
- Como funciona o JavaScript: uma comparação com o WebAssembly + por quê, em certos casos, é melhor usá-lo sobre JavaScript
- Como o JavaScript funciona: Os blocos de construção dos Web Workers + 5 casos quando você deve usá-los
- Como o JavaScript funciona: a mecânica das notificações por push na Web
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çãodisconnect
- para de escutar alteraçõestakeRecords
- 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