¿Por qué se dice que el concepto de DOM virtual de React es más eficaz que la verificación de modelos sucios?

372

Vi una charla de desarrollo de React en ( Pete Hunt: React: repensar las mejores prácticas - JSConf EU 2013 ) y el orador mencionó que la verificación sucia del modelo puede ser lenta. Pero, ¿no es el cálculo de la diferencia entre DOM virtuales en realidad incluso menos eficaz ya que el DOM virtual, en la mayoría de los casos, debería ser más grande que el modelo?

Realmente me gusta la potencia potencial del DOM virtual (especialmente la representación del lado del servidor) pero me gustaría conocer todos los pros y los contras.

Daniil
fuente
Creo que también podrías mencionar esta charla youtube.com/watch?v=-DX3vJiqxm4, donde habla específicamente sobre puntos de referencia.
inafalcao

Respuestas:

493

Soy el autor principal de un módulo virtual-dom , por lo que podría responder sus preguntas. De hecho, hay 2 problemas que deben resolverse aquí

  1. ¿Cuándo vuelvo a renderizar? Respuesta: cuando observo que los datos están sucios.
  2. ¿Cómo re-renderizo eficientemente? Respuesta: Usar un DOM virtual para generar un parche DOM real

En React, cada uno de sus componentes tiene un estado. Este estado es como un observable que puede encontrar en knockout u otras bibliotecas de estilo MVVM. Esencialmente, React sabe cuándo volver a renderizar la escena porque puede observar cuándo cambian estos datos. La comprobación sucia es más lenta que las observables porque debe sondear los datos a intervalos regulares y verificar todos los valores de la estructura de datos de forma recursiva. En comparación, establecer un valor en el estado le indicará al oyente que algún estado ha cambiado, por lo que React simplemente puede escuchar los eventos de cambio en el estado y volver a procesar la cola.

El DOM virtual se utiliza para una representación eficiente del DOM. Esto no está realmente relacionado con la verificación sucia de sus datos. Puede volver a renderizar utilizando un DOM virtual con o sin verificación sucia. Tiene razón en que hay algo de sobrecarga en el cálculo de la diferencia entre dos árboles virtuales, pero la diferencia de DOM virtual consiste en comprender qué necesita actualizarse en el DOM y no si sus datos han cambiado o no. De hecho, el algoritmo diff es un verificador sucio, pero se usa para ver si el DOM está sucio.

Nuestro objetivo es volver a representar el árbol virtual solo cuando el estado cambia. Por lo tanto, usar un observable para verificar si el estado ha cambiado es una forma eficiente de evitar reproducciones innecesarias, lo que causaría muchas diferencias innecesarias en los árboles. Si nada ha cambiado, no hacemos nada.

Un DOM virtual es bueno porque nos permite escribir nuestro código como si estuviéramos renderizando de nuevo toda la escena. Detrás de escena queremos calcular una operación de parche que actualice el DOM para que se vea como esperamos. Entonces, aunque el algoritmo virtual de diferencias / parches DOM probablemente no sea la solución óptima , nos brinda una forma muy agradable de expresar nuestras aplicaciones. Simplemente declaramos exactamente lo que queremos y React / virtual-dom resolverá cómo hacer que su escena se vea así. No tenemos que manipular DOM manualmente ni confundirnos con el estado DOM anterior. Tampoco tenemos que volver a renderizar toda la escena, lo que podría ser mucho menos eficiente que parchearla.

Matt Esch
fuente
1
¿React realiza una comprobación sucia de los accesorios de los componentes? Pregunto porque no hay función setProps ().
bennlich
1
¿Cuál sería un ejemplo de eso unnecessary re-renders?
vsync
99
Cuando dice "Entonces, si bien el algoritmo virtual de diferencias / parches DOM probablemente no sea la solución óptima", ¿tiene en mente una solución teóricamente más óptima?
CMCDragonkai
3
Esto no parece responder la pregunta. React requiere que use setState para indicar que el estado ha cambiado. Si pudiera hacerlo this.state.cats = 99, aún necesitaría una verificación sucia para verificar el cambio de modelo, al igual que Angular dirty verifica el árbol $ scope. Esta no es una comparación de la velocidad de las dos técnicas, es simplemente una afirmación de que React no realiza una comprobación sucia porque en su lugar tiene un configurador de estilo Backbone.
superluminary
133

Recientemente leí un artículo detallado sobre el algoritmo diff de React aquí: http://calendar.perfplanet.com/2013/diff/ . Por lo que entiendo, lo que hace que React sea rápido es:

  • Operaciones de lectura / escritura DOM por lotes.
  • Actualización eficiente de subárbol solamente.

En comparación con el control sucio, las diferencias clave de la OMI son:

  1. Comprobación sucia del modelo : el componente React se establece explícitamente como sucio cada vez que setStatese llama, por lo que no hay comparación (de los datos) necesaria aquí. Para la verificación sucia, la comparación (de los modelos) siempre ocurre en cada ciclo de resumen.

  2. Actualización del DOM : las operaciones del DOM son muy caras porque la modificación del DOM también se aplicará y calculará estilos CSS, diseños. El tiempo ahorrado por la modificación innecesaria del DOM puede ser mayor que el tiempo dedicado a diferenciar el DOM virtual.

El segundo punto es aún más importante para los modelos no triviales, como uno con una gran cantidad de campos o una lista grande. Un cambio de campo del modelo complejo dará como resultado solo las operaciones necesarias para los elementos DOM que involucren ese campo, en lugar de la vista / plantilla completa.

tungd
fuente
1
En realidad, también he leído algunos artículos, así que ahora (al menos en general) cómo funciona, solo quería descubrir por qué puede ser más eficiente que la verificación sucia del modelo. Y 1) Sí, no compara modelos pero compara dom virtual mucho más grande 2) La verificación sucia del modelo nos brinda la capacidad de actualizar solo lo que es necesario (como Angular lo hace)
Daniil
Creo que solo se deben comparar partes del DOM virtual correspondiente al componente modificado, mientras que la verificación sucia ocurre en cada ciclo de resumen, para cada valor en cada ámbito, incluso si nada ha cambiado. Si se modifica una gran cantidad de datos, entonces Virtual DOM sería menos eficiente, pero no para pequeños cambios de datos.
tungd
1
Hablando de Angular, debido a que los observadores también pueden mutar el estado mientras se resumen, $scope.$digestse ejecuta varias veces por ciclo de resumen, por lo que es tiempo múltiple de comparación de datos completos versus tiempo único de comparación de árbol DOM virtual parcial.
tungd
44
Es triste que muchos desarrolladores inteligentes inventen "montañas" de trucos para lidiar con el DOM "lento" y así sucesivamente, en lugar de centrar nuestra atención combinada en arreglar los navegadores y eliminar la lentitud del DOM de una vez por todas. Es como utilizar todos los recursos de la humanidad para investigar formas de tratar el cáncer y mejorar la vida de un paciente, en lugar de simplemente reparar el cáncer en sí. Ridículas
vsync
@vsync El DOM necesita mostrar cosas en la pantalla. Un DOM virtual no lo hace. Incluso con un DOM ideal, la creación de un DOM virtual será más rápida.
Jehan
75

Realmente me gusta la potencia potencial del DOM virtual (especialmente la representación del lado del servidor) pero me gustaría conocer todos los pros y los contras.

- OP

React no es la única biblioteca de manipulación DOM. Le recomiendo que comprenda las alternativas leyendo este artículo de Auth0 que incluye explicaciones detalladas y puntos de referencia. Destacaré aquí sus pros y sus contras, como usted preguntó:

DOM virtual de React.js

ingrese la descripción de la imagen aquí

PROS

  • Algoritmo "diferencial" rápido y eficiente
  • Frontales múltiples (JSX, hiperescrito)
  • Lo suficientemente ligero como para ejecutarse en dispositivos móviles
  • Mucha tracción y mente compartida
  • Se puede usar sin React (es decir, como un motor independiente)

CONTRAS

  • Copia completa en memoria del DOM (mayor uso de memoria)
  • Sin diferenciación entre elementos estáticos y dinámicos.

Ember.js 'Glimmer

ingrese la descripción de la imagen aquí

PROS

  • Algoritmo diferencial rápido y eficiente
  • Diferenciación entre elementos estáticos y dinámicos.
  • 100% compatible con la API de Ember (obtienes los beneficios sin actualizaciones importantes de tu código existente)
  • Representación ligera en memoria del DOM

CONTRAS

  • Destinado a ser utilizado solo en Ember
  • Solo hay una interfaz disponible

DOM incremental

ingrese la descripción de la imagen aquí

PROS

  • Uso reducido de memoria
  • API simple
  • Se integra fácilmente con muchos frontends y frameworks (desde el principio como un motor de plantillas de backend)

CONTRAS

  • No es tan rápido como otras bibliotecas (esto es discutible, vea los puntos de referencia a continuación)
  • Menos uso de la mente y la comunidad
falsarella
fuente
La representación de la manipulación DOM de ReactJS me parece un poco fuera de lugar. El DOM virtual de ReactJS es el que cambia por completo, no el DOM real, ¿correcto? Estoy mirando el artículo original al que se hace referencia y aquí está lo que veo: teropa.info/images/onchange_vdom_change.svg . teropa.info/blog/2015/03/02/…
smile.al.d.way
35

Aquí hay un comentario del miembro del equipo React Sebastian Markbåge que arroja algo de luz:

React hace la diferencia en la salida (que es un formato serializable conocido, atributos DOM). Esto significa que los datos de origen pueden tener cualquier formato. Pueden ser estructuras de datos inmutables y estados dentro de los cierres.

El modelo angular no preserva la transparencia referencial y, por lo tanto, es inherentemente mutable. Cambia el modelo existente para seguir los cambios. ¿Qué sucede si su fuente de datos son datos inmutables o una nueva estructura de datos cada vez (como una respuesta JSON)?

Comprobación sucia y Object.observe no funciona en el estado del alcance de cierre.

Obviamente, estas dos cosas son muy limitantes para los patrones funcionales.

Además, cuando la complejidad de su modelo crece, se vuelve cada vez más costoso hacer un seguimiento sucio. Sin embargo, si solo difiere en el árbol visual, como React, entonces no aumentará tanto, ya que la cantidad de datos que puede mostrar en la pantalla en cualquier punto está limitada por las IU. El enlace anterior de Pete cubre más de los beneficios de rendimiento.

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

Sophie Alpert
fuente
2
En realidad sobre el último párrafo: debería estar equivocado: el modelo es más grande que el dom virtual porque para cada valor de modelo hay (en la mayoría de los casos) al menos un elemento dom virtual (y generalmente mucho más de uno). ¿Por qué quiero un modelo que no se muestra?
Daniil
2
Paginación de colecciones en caché.
kentor
-2

Dom virtual no es inventado por reaccionar. Es parte de HTML dom. Es liviano y está separado de los detalles de implementación específicos del navegador.

Podemos pensar que el DOM virtual es una copia local y simplificada de HTML DOM de React. Le permite a React hacer sus cálculos dentro de este mundo abstracto y omitir las operaciones DOM "reales", a menudo lentas y específicas del navegador. En realidad, no hay grandes diferencias entre DOM y DOM VIRTUAL.

A continuación se muestran los puntos por los que se usa Virtual Dom (fuente Virtual DOM en ReactJS ):

Cuando tu lo hagas:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. El navegador necesita analizar el HTML
  2. Elimina el elemento hijo de elementId
  3. Actualiza el valor DOM con nuevo valor
  4. Vuelva a calcular el CSS para el padre y el hijo
  5. Actualice el diseño, es decir, cada elemento coordina exactamente en la pantalla
  6. Atraviesa el árbol de renderizado y píntalo en la pantalla del navegador

Volver a calcular el CSS y los diseños modificados utiliza algoritmos complejos y afectan el rendimiento.

Además de actualizar las propiedades DOM, es decir. valores. Sigue un algoritmo.

Ahora, suponga que si actualiza DOM 10 veces directamente, todos los pasos anteriores se ejecutarán uno por uno y la actualización de los algoritmos DOM llevará tiempo para actualizar los valores DOM.

Por eso, el DOM real es más lento que el DOM virtual.

Hemant Nagarkoti
fuente
3
Sobre el ejemplo, si está modificando el dom directamente o mediante un dom virtual, finalmente, en ambos casos, está cambiando el dom.
magallanes
Sí, en ambos casos estamos actualizando dom, pero en el caso de dom virtual, actualiza en particular esa clave (definida de manera única por el algoritmo de reacción) o solo la etiqueta del elemento. Mientras que la actualización de dom actualiza o actualiza todo el dom completamente.
Hemant Nagarkoti
11
He visto este artículo en hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 . Tal vez sea mejor señalar la fuente si no eres el autor.
Jinggang
2
"Por eso, el DOM real es más lento que el DOM virtual". No señor, simplemente está equivocado.
Roecrew