Perché si dice che il concetto di Virtual DOM di React sia più performante del controllo del modello sporco?


372

Ho visto un discorso degli sviluppatori React a ( Pete Hunt: React: ripensare le migliori pratiche - JSConf EU 2013 ) e l'oratore ha affermato che il controllo sporco del modello può essere lento. Ma il calcolo della differenza tra DOM virtuali in realtà non è nemmeno meno performante poiché il DOM virtuale, nella maggior parte dei casi, dovrebbe essere più grande del modello?

Mi piace molto la potenza potenziale del Virtual DOM (in particolare il rendering lato server) ma vorrei conoscere tutti i pro e i contro.


Penso che potresti parlare anche di questo discorso su youtube.com/watch?v=-DX3vJiqxm4 in cui parla specificamente di benchmark.
Inafalcao,

Risposte:


493

Sono l'autore principale di un modulo di dom virtuale , quindi potrei essere in grado di rispondere alle tue domande. In effetti, ci sono 2 problemi che devono essere risolti qui

  1. Quando posso eseguire nuovamente il rendering? Risposta: quando osservo che i dati sono sporchi.
  2. Come posso eseguire nuovamente il rendering in modo efficiente? Risposta: utilizzo di un DOM virtuale per generare una vera patch DOM

In React, ciascuno dei tuoi componenti ha uno stato. Questo stato è come un osservabile che potresti trovare in knockout o in altre librerie di stile MVVM. In sostanza, React sa quando eseguire nuovamente il rendering della scena perché è in grado di osservare quando questi dati cambiano. Il controllo sporco è più lento degli osservabili perché è necessario eseguire il polling dei dati a intervalli regolari e verificare ricorsivamente tutti i valori nella struttura dei dati. In confronto, l'impostazione di un valore sullo stato segnalerà a un ascoltatore che alcuni stati sono cambiati, quindi React può semplicemente ascoltare gli eventi di cambiamento sullo stato e mettere in coda il rendering.

Il DOM virtuale viene utilizzato per un efficiente rendering del DOM. Questo non è in realtà correlato al controllo sporco dei dati. È possibile eseguire nuovamente il rendering utilizzando un DOM virtuale con o senza controllo sporco. Hai ragione nel dire che c'è un sovraccarico nel calcolare la diff tra due alberi virtuali, ma la diff virtuale DOM riguarda la comprensione di ciò che deve essere aggiornato nel DOM e non se i tuoi dati sono cambiati o meno. In realtà, l'algoritmo diff è un controllo sporco stesso ma viene utilizzato per vedere se il DOM è invece sporco.

Il nostro obiettivo è di rendere nuovamente l'albero virtuale solo quando lo stato cambia. Quindi, usare un osservabile per verificare se lo stato è cambiato è un modo efficace per prevenire ricalcoli non necessari, che causerebbero molte differenze dell'albero non necessarie. Se nulla è cambiato, non facciamo nulla.

Un DOM virtuale è bello perché ci permette di scrivere il nostro codice come se dovessimo ridigitare l'intera scena. Dietro le quinte vogliamo calcolare un'operazione di patch che aggiorna il DOM per apparire come ci aspettiamo. Quindi, mentre l'algoritmo di diff / patch DOM virtuale probabilmente non è la soluzione ottimale , ci offre un modo molto piacevole per esprimere le nostre applicazioni. Dichiariamo esattamente ciò che vogliamo e React / virtual-dom elaborerà come far apparire la tua scena così. Non è necessario eseguire la manipolazione manuale del DOM o confondersi sul precedente stato DOM. Non è nemmeno necessario eseguire nuovamente il rendering dell'intera scena, il che potrebbe essere molto meno efficiente rispetto all'applicazione di patch.


1
React esegue controlli sporchi sugli oggetti di scena? Lo chiedo perché non esiste una funzione setProps ().
bennlich,


1
quale sarebbe un esempio di tale unnecessary re-renders?
vsync,

9
Quando dici "Quindi, mentre l'algoritmo di diff / patch DOM virtuale probabilmente non è la soluzione ottimale", hai in mente una soluzione teoricamente più ottimale?
CMCDragonkai

3
Questo non sembra rispondere alla domanda. React richiede di utilizzare setState per segnalare che lo stato è cambiato. Se fossi in grado di farlo this.state.cats = 99, avresti comunque bisogno di un controllo sporco per verificare la modifica del modello, proprio come Angular sporco controlla l'albero $ scope. Questo non è un confronto della velocità delle due tecniche, è semplicemente un'affermazione secondo cui React non esegue controlli sporchi perché ha invece un setter di stile Backbone.
superluminario

133

Di recente ho letto un articolo dettagliato sull'algoritmo diff di React qui: http://calendar.perfplanet.com/2013/diff/ . Da quello che ho capito, ciò che rende React veloce è:

  • Operazioni di lettura / scrittura DOM in batch.
  • Aggiornamento efficiente solo del sottoalbero.

Rispetto al controllo sporco, le principali differenze IMO sono:

  1. Modello di controllo sporco : il componente React viene impostato esplicitamente come sporco ogni volta che setStateviene chiamato, quindi non è necessario un confronto (dei dati) qui. Per il controllo sporco, il confronto (dei modelli) avviene sempre ogni ciclo digest.

  2. Aggiornamento DOM : le operazioni DOM sono molto costose perché la modifica del DOM applicherà e calcolerà anche stili, layout CSS. Il tempo risparmiato dalla modifica del DOM non necessaria può essere più lungo del tempo impiegato per diffondere il DOM virtuale.

Il secondo punto è ancora più importante per i modelli non banali come uno con un'enorme quantità di campi o un grande elenco. Una modifica del campo del modello complesso comporterà solo le operazioni necessarie per gli elementi DOM che coinvolgono quel campo, anziché l'intera vista / modello.


1
In realtà ho letto anche alcuni articoli, quindi ora (almeno in generale) come funziona, volevo solo capire perché può essere più efficiente del controllo sporco del modello. E 1) Sì, non confronta i modelli ma confronta dom virtuali molto più grandi 2) Il controllo sporco del modello ci fornisce la possibilità di aggiornare solo ciò che è necessario (come fa Angular)
Daniil

Credo che solo le parti del DOM virtuale corrispondenti al componente modificato debbano essere confrontate, mentre il controllo sporco avviene ogni ciclo digest, per ogni valore su ogni ambito, anche se nulla è cambiato. Se viene modificata una grande quantità di dati, Virtual DOM sarebbe meno efficiente, ma non per una piccola modifica dei dati.
pubblicato il

1
Parlando di Angular, poiché gli osservatori possono anche mutare lo stato durante il digest, $scope.$digestvengono eseguiti più volte per ciclo di digest, quindi è più volte del confronto completo dei dati rispetto al singolo tempo del confronto parziale dell'albero virtuale DOM.
pubblicato il

4
è triste che così tanti sviluppatori intelligenti inventino "montagne" di trucchi per gestire DOM "lenti" e così via, invece di concentrare la nostra attenzione combinata solo per riparare i browser stessi e liberarci della lentezza DOM una volta per tutte. è come usare tutte le risorse dell'umanità per cercare modi per affrontare il cancro e migliorare la vita di un paziente, invece di riparare solo il cancro stesso. Ridicolo.
vsync,

@vsync Il DOM deve visualizzare elementi sullo schermo. Un DOM virtuale no. Anche con alcuni DOM dalle prestazioni ideali, la creazione di un DOM virtuale sarà più veloce.
Jehan,

75

Mi piace molto la potenza potenziale del Virtual DOM (in particolare il rendering lato server) ma vorrei conoscere tutti i pro e i contro.

-- OPERAZIONE

React non è l'unica libreria di manipolazione DOM. Ti incoraggio a capire le alternative leggendo questo articolo di Auth0 che include spiegazioni dettagliate e parametri di riferimento. Metterò in evidenza qui i loro pro e contro, come hai chiesto:

DOM virtuale di React.js

inserisci qui la descrizione dell'immagine

PROFESSIONISTI

  • Algoritmo "diffing" rapido ed efficiente
  • Frontend multipli (JSX, iperscript)
  • Abbastanza leggero per funzionare su dispositivi mobili
  • Molta trazione e mindshare
  • Può essere utilizzato senza React (ovvero come motore indipendente)

CONS

  • Copia in memoria completa del DOM (utilizzo della memoria maggiore)
  • Nessuna differenziazione tra elementi statici e dinamici

Ember.js 'Glimmer

inserisci qui la descrizione dell'immagine

PROFESSIONISTI

  • Algoritmo di diffing rapido ed efficiente
  • Differenziazione tra elementi statici e dinamici
  • 100% compatibile con l'API di Ember (ottieni i vantaggi senza importanti aggiornamenti del codice esistente)
  • Rappresentazione in-memory leggera del DOM

CONS

  • Destinato ad essere utilizzato solo in Ember
  • Un solo frontend disponibile

DOM incrementale

inserisci qui la descrizione dell'immagine

PROFESSIONISTI

  • Utilizzo della memoria ridotto
  • API semplice
  • Si integra facilmente con molti frontend e framework (intesi come backend del motore modello sin dall'inizio)

CONS

  • Non veloce come le altre librerie (questo è discutibile, vedere i benchmark di seguito)
  • Meno condivisione della mente e uso della comunità

La rappresentazione della manipolazione DOM di ReactJS mi sembra poco. Il DOM virtuale di ReactJS è quello che cambia completamente, non l'attuale DOM - corretto? Sto guardando l'articolo originale i riferimenti all'articolo a cui si fa riferimento ed ecco cosa vedo - teropa.info/images/onchange_vdom_change.svg . teropa.info/blog/2015/03/02/…
smile.al.d.way

35

Ecco un commento del membro del team React Sebastian Markbåge che fa luce:

React fa la differenza sull'output (che è un formato serializzabile noto, attributi DOM). Ciò significa che i dati di origine possono essere di qualsiasi formato. Può essere strutture di dati immutabili e stato all'interno delle chiusure.

Il modello angolare non conserva la trasparenza referenziale e pertanto è intrinsecamente mutabile. Muta il modello esistente per tenere traccia delle modifiche. Che cosa succede se l'origine dati sono dati immutabili o una nuova struttura di dati ogni volta (come una risposta JSON)?

Il controllo sporco e Object.observe non funzionano sullo stato dell'ambito di chiusura.

Queste due cose sono ovviamente molto limitanti ai modelli funzionali.

Inoltre, quando la complessità del modello aumenta, diventa sempre più costoso eseguire il monitoraggio sporco. Tuttavia, se si differenzia solo sull'albero visivo, come React, allora non cresce tanto poiché la quantità di dati che è possibile mostrare sullo schermo in un determinato punto è limitata dalle interfacce utente. Il link sopra di Pete copre molti dei vantaggi perf.

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


2
In realtà sull'ultimo paragrafo: dovrebbe essere sbagliato: il modello è più grande del dom virtuale perché per ogni valore del modello esiste (nella maggior parte dei casi) almeno un elemento dom virtuale (e di solito molto più di uno). Perché voglio un modello che non viene mostrato?
Daniil,

2
Collezioni impaginate nella cache.
Kent,

-2

Virtual Dom non è stato inventato da reazioni. Fa parte del dom HTML. È leggero e distaccato dai dettagli di implementazione specifici del browser.

Possiamo pensare al DOM virtuale come alla copia locale e semplificata di React del DOM HTML. Permette a React di eseguire i suoi calcoli all'interno di questo mondo astratto e di saltare le "reali" operazioni DOM, spesso lente e specifiche del browser. In realtà non esiste una grande differenza tra DOM e VIRTUAL DOM.

Di seguito sono riportati i punti per cui viene utilizzato Virtual Dom ( DOM virtuale di origine in ReactJS ):

Quando lo fai:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. Il browser deve analizzare l'HTML
  2. Rimuove l'elemento figlio di elementId
  3. Aggiorna il valore DOM con un nuovo valore
  4. Ricalcola i CSS per genitore e figlio
  5. Aggiorna il layout, ovvero ogni elemento corrisponde esattamente alle coordinate sullo schermo
  6. Attraversa l'albero di rendering e disegnalo sul display del browser

Il ricalcolo del CSS e dei layout modificati utilizza un algoritmo complesso e influiscono sulle prestazioni.

Oltre ad aggiornare le proprietà del DOM, ad es. valori. Segue un algoritmo.

Supponiamo ora che aggiorni DOM 10 volte direttamente, quindi tutti i passaggi precedenti verranno eseguiti uno alla volta e l'aggiornamento degli algoritmi DOM richiederà del tempo per aggiornare i valori DOM.

Questo è il motivo per cui Real DOM è più lento del DOM virtuale.


3
Per quanto riguarda l'esempio, se stai modificando il dom direttamente o tramite un dom virtuale, infine per entrambi i casi stai cambiando il dom.
Magallanes,

Sì, in entrambi i casi stiamo aggiornando dom, ma in caso di dom virtuale aggiorna in particolare quel campo chiave (definito in modo univoco diverso dall'algoritmo da reagire) o solo il tag elemento. Considerando che l'aggiornamento dom aggiorna o ha aggiornato completamente l'intero dom.
Hemant Nagarkoti,

11
Ho visto questo articolo da hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 . Forse è meglio indicare la fonte se non sei l'autore.
Jinggang,

2
"Questo è il motivo per cui Real DOM è più lento del DOM virtuale." No signore, ti sbagli di grosso.
Roecrew
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.