Por que o conceito de DOM virtual da React é considerado mais eficiente do que a verificação de modelos sujos?

372

Vi uma palestra do desenvolvedor do React em ( Pete Hunt: React: Repensando as melhores práticas - JSConf EU 2013 ) e o palestrante mencionou que a verificação suja do modelo pode ser lenta. Mas o cálculo da diferença entre DOMs virtuais na verdade é ainda menos eficiente, já que o DOM virtual, na maioria dos casos, deve ser maior que o modelo?

Eu realmente gosto do poder potencial do DOM virtual (especialmente a renderização no servidor), mas gostaria de saber todos os prós e contras.

Daniil
fonte
Eu acho que você poderia mencionar essa conversa também youtube.com/watch?v=-DX3vJiqxm4, onde ele fala especificamente sobre benchmarks.
Inafalcao

Respostas:

493

Eu sou o autor principal de um módulo de dom virtual , então talvez eu possa responder às suas perguntas. De fato, existem 2 problemas que precisam ser resolvidos aqui

  1. Quando eu re-renderizo? Resposta: Quando observo que os dados estão sujos.
  2. Como renderizo de forma eficiente? Resposta: Usando um DOM virtual para gerar um patch DOM real

No React, cada um de seus componentes possui um estado. Esse estado é como um observável que você pode encontrar em knockout ou em outras bibliotecas de estilo MVVM. Essencialmente, o React sabe quando renderizar novamente a cena porque é capaz de observar quando esses dados são alterados. A verificação suja é mais lenta que as observáveis, porque você deve pesquisar os dados em um intervalo regular e verificar todos os valores na estrutura de dados recursivamente. Em comparação, a definição de um valor no estado sinalizará a um ouvinte que algum estado foi alterado, portanto o React pode simplesmente ouvir eventos de alteração no estado e enfileirar a nova renderização.

O DOM virtual é usado para re-renderização eficiente do DOM. Isso não está realmente relacionado à verificação suja de seus dados. Você pode renderizar novamente usando um DOM virtual com ou sem verificação suja. Você está certo quanto ao fato de haver alguma sobrecarga na computação da diferença entre duas árvores virtuais, mas a diferença virtual do DOM é sobre o que precisa ser atualizado no DOM e não se seus dados foram ou não alterados. De fato, o algoritmo diff é um verificador sujo, mas é usado para verificar se o DOM está sujo.

Nosso objetivo é renderizar novamente a árvore virtual somente quando o estado mudar. Portanto, usar um observável para verificar se o estado mudou é uma maneira eficiente de evitar renderizações desnecessárias, o que causaria muitas diferenças de árvore desnecessárias. Se nada mudou, não fazemos nada.

Um DOM virtual é bom porque nos permite escrever nosso código como se estivéssemos re-renderizando a cena inteira. Nos bastidores, queremos calcular uma operação de patch que atualiza o DOM para ter a aparência esperada. Portanto, embora o algoritmo diff / patch virtual do DOM provavelmente não seja a solução ideal , ele nos fornece uma maneira muito agradável de expressar nossos aplicativos. Apenas declaramos exatamente o que queremos e o React / virtual-dom descobrirá como tornar sua cena assim. Não precisamos manipular manualmente o DOM ou ficar confusos sobre o estado anterior do DOM. Também não precisamos renderizar novamente toda a cena, o que poderia ser muito menos eficiente do que corrigi-la.

Matt Esch
fonte
11
O React faz uma verificação suja nos acessórios de componentes? Eu pergunto porque não há função setProps ().
bennlich
11
qual seria um exemplo disso unnecessary re-renders?
vsync
9
Quando você diz "Então, embora o algoritmo virtual de diff / patch do DOM provavelmente não seja a solução ideal", você tem em mente uma solução teoricamente mais ideal?
precisa saber é o seguinte
3
Isso parece não responder à pergunta. React requer que você use setState para sinalizar que o estado mudou. Se você pudesse fazer this.state.cats = 99isso, ainda precisaria de verificação suja para verificar a alteração do modelo, assim como Angular dirty verifica a árvore $ scope. Esta não é uma comparação da velocidade das duas técnicas, é simplesmente uma declaração de que o React não faz uma verificação suja porque, em vez disso, possui um configurador de estilo Backbone.
superluminary
133

Recentemente, li um artigo detalhado sobre o algoritmo diff do React aqui: http://calendar.perfplanet.com/2013/diff/ . Pelo que entendi, o que faz o React rápido é:

  • Operações de leitura / gravação do DOM em lote.
  • Atualização eficiente apenas da subárvore.

Comparadas à verificação suja, as principais diferenças da IMO são:

  1. Modelo de verificação suja : o componente React é explicitamente definido como sujo sempre que setStateé chamado, portanto, não há comparação (dos dados) necessária aqui. Para verificação suja, a comparação (dos modelos) sempre acontece a cada loop de resumo.

  2. Atualização do DOM : as operações do DOM são muito caras, porque a modificação do DOM também se aplica e calcula estilos e layouts de CSS. O tempo economizado com a modificação desnecessária do DOM pode ser maior que o tempo gasto diferenciando o DOM virtual.

O segundo ponto é ainda mais importante para modelos não triviais, como um com grande quantidade de campos ou grande lista. Uma alteração de campo do modelo complexo resultará apenas nas operações necessárias para os elementos DOM que envolvem esse campo, em vez de toda a visualização / modelo.

tungd
fonte
11
Na verdade, eu também li alguns artigos, então agora (pelo menos em geral) como funciona, eu só queria descobrir por que ele pode ser mais eficiente do que a verificação suja do modelo. E 1) modelos Yup, não comparar, mas se compara muito maior dom virtual 2) Dirty-cheque do modelo nos fornecer capacidade de atualizar apenas o necessário também (como Angular faz)
Daniil
Acredito que apenas partes do DOM virtual correspondente ao componente alterado precisam ser comparadas, enquanto a verificação suja acontece a cada loop de digestão, a todos os valores em todos os escopos, mesmo que nada tenha mudado. Se uma grande quantidade de dados fosse alterada, o Virtual DOM seria menos eficiente, mas não para pequenas alterações de dados.
tungd
11
Por falar em Angular, como os observadores também podem alterar o estado durante a digestão, ela $scope.$digesté executada várias vezes por ciclo de digestão, portanto, é tempo múltiplo de comparação de dados completa versus tempo único de comparação parcial da árvore DOM virtual.
tungd
4
é triste que muitos desenvolvedores inteligentes inventem "montanhas" de truques para lidar com o DOM "lento" e assim por diante, em vez de focar nossa atenção combinada em apenas consertar os próprios navegadores e nos livrar da lentidão do DOM de uma vez por todas. é como usar todos os recursos da humanidade para pesquisar maneiras de lidar com o câncer e melhorar a vida de um paciente, em vez de apenas consertar o próprio câncer. Ridículos.
Vsync
@vsync O DOM precisa exibir itens na tela. Um DOM virtual não. Mesmo com um DOM com desempenho ideal, a criação de um DOM virtual será mais rápida.
Jehan 15/05
75

Eu realmente gosto do poder potencial do DOM virtual (especialmente a renderização no servidor), mas gostaria de saber todos os prós e contras.

- OP

React não é a única biblioteca de manipulação de DOM. Convido você a entender as alternativas lendo este artigo do Auth0, que inclui explicações e referências detalhadas. Vou destacar aqui seus prós e contras, como você perguntou:

DOM virtual do React.js.

insira a descrição da imagem aqui

PROS

  • Algoritmo "diferencial" rápido e eficiente
  • Múltiplas interfaces (JSX, hiperescrito)
  • Leve o suficiente para rodar em dispositivos móveis
  • Muita tração e atenção
  • Pode ser usado sem o React (ou seja, como um mecanismo independente)

CONS

  • Cópia completa na memória do DOM (maior uso de memória)
  • Nenhuma diferenciação entre elementos estáticos e dinâmicos

Ember.js 'Glimmer

insira a descrição da imagem aqui

PROS

  • Algoritmo diffing rápido e eficiente
  • Diferenciação entre elementos estáticos e dinâmicos
  • 100% compatível com a API da Ember (você obtém os benefícios sem grandes atualizações no seu código existente)
  • Representação leve na memória do DOM

CONS

  • Destinado a ser usado apenas no Ember
  • Apenas um front-end disponível

DOM incremental

insira a descrição da imagem aqui

PROS

  • Uso de memória reduzido
  • API simples
  • Integra-se facilmente a muitos front-end e estruturas (como um mecanismo de modelo de back-end desde o início)

CONS

  • Não é tão rápido quanto outras bibliotecas (isso é discutível, veja os benchmarks abaixo)
  • Menos compartilhamento de ideias e uso da comunidade
falsarella
fonte
A representação da manipulação DOM do ReactJS parece pouco para mim. O DOM virtual do ReactJS é aquele que muda completamente, não o DOM real - correto? Eu estou olhando para o artigo original, o artigo referenciado faz referência e aqui está o que eu vejo - teropa.info/images/onchange_vdom_change.svg . teropa.info/blog/2015/03/02/…
smile.al.d.way
35

Aqui está um comentário do membro da equipe do React, Sebastian Markbåge, que esclarece:

React faz a diferença na saída (que é um formato serializável conhecido, atributos DOM). Isso significa que os dados de origem podem ter qualquer formato. Pode ser estruturas de dados imutáveis ​​e estado dentro de fechamentos.

O modelo Angular não preserva a transparência referencial e, portanto, é inerentemente mutável. Você modifica o modelo existente para rastrear alterações. E se sua fonte de dados for imutável ou uma nova estrutura de dados sempre (como uma resposta JSON)?

A verificação suja e Object.observe não funciona no estado do escopo de fechamento.

Essas duas coisas são muito limitantes aos padrões funcionais, obviamente.

Além disso, quando a complexidade do modelo aumenta, fica cada vez mais caro fazer o rastreamento sujo. No entanto, se você diferenciar apenas a árvore visual, como React, ela não aumentará tanto, pois a quantidade de dados que você pode mostrar na tela em um determinado momento é limitada pelas UIs. O link de Pete acima cobre mais dos benefícios do perf.

https://news.ycombinator.com/item?id=6937668

Sophie Alpert
fonte
2
Na verdade, sobre o último parágrafo: deve estar errado: o modelo é maior que o dom virtual, porque para cada valor de modelo existe (na maioria dos casos) pelo menos um elemento dom virtual (e geralmente muito mais que um). Por que eu quero modelo que não é mostrado?
187 Daniil
2
Paginando coleções em cache.
Kentor
-2

Dom virtual não é inventado por reagir. Faz parte do HTML dom. É leve e desanexado dos detalhes de implementação específicos do navegador.

Podemos pensar no DOM virtual como a cópia local e simplificada do HTML do React. Ele permite que o React faça seus cálculos nesse mundo abstrato e pule as operações DOM "reais", geralmente lentas e específicas do navegador. Na verdade, não há grande diferença entre DOM e DOM VIRTUAL.

Abaixo estão os pontos pelos quais o Virtual Dom é usado ( DOM virtual de origem no ReactJS ):

Quando você faz:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. O navegador precisa analisar o HTML
  2. Remove o elemento filho de elementId
  3. Atualiza o valor DOM com novo valor
  4. Recalcular o css para o pai e o filho
  5. Atualizar o layout, ou seja, cada elemento exato coordena na tela
  6. Percorra a árvore de renderização e pinte-a na tela do navegador

Recalcular o CSS e os layouts alterados usa algoritmo complexo e afeta o desempenho.

Bem como atualizar as propriedades do DOM, ie. valores. Segue um algoritmo.

Agora, suponha que se você atualizar o DOM 10 vezes diretamente, todas as etapas acima serão executadas uma a uma e a atualização dos algoritmos do DOM levará tempo para atualizar os valores do DOM.

É por isso que o Real DOM é mais lento que o DOM virtual.

Hemant Nagarkoti
fonte
3
Sobre o exemplo, se você está modificando o dom diretamente ou através de um dom virtual, finalmente, para os dois casos, você está mudando o dom.
magallanes
Sim, em ambos os casos, estamos atualizando o dom, mas, no caso do virtual virtual, ele atualiza em particular aquele campo de chave (definido exclusivamente pelo algoritmo difere do react) e somente o tag do campo. Enquanto a atualização do dom atualiza ou atualiza todo o dom completamente.
Hemant Nagarkoti
11
Vi este artigo em hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 . Talvez seja melhor apontar a fonte se você não é o autor.
Jinggang
2
"É por isso que o Real DOM é mais lento que o DOM virtual." Não senhor, você está errado.
Roecrew