¿Se puede explicar de forma sencilla el algoritmo de diferenciación en la parte frontal de la página web?
Un estudiante preguntó: ¿Puedes presentarnos el algoritmo de diferenciación en detalle?
Lea este artículo para obtener más detalles. Si tiene alguna pregunta, deje un mensaje para discutirla.
Dado que el algoritmo diff es el punto central clave de vue2.x, vue3.x y reaccionar, comprender el algoritmo diff le ayudará a comprender la esencia de cada marco.
Cuando hablamos del algoritmo diff, tenemos que hablar de Virtual Dom porque los dos están estrechamente relacionados.
Por ejemplo:
Espera
Primero echemos un vistazo al Dom virtual, que es un DOM implementado mediante simulación JS. Luego, la dificultad radica en cómo. para determinar la diferencia entre los objetos antiguos y nuevos.
Dom es una estructura de múltiples árboles, por lo que si necesita comparar completamente las diferencias entre dos árboles, la complejidad temporal del algoritmo es O (n ^ 3), lo cual es difícil de aceptar, especialmente cuando n es grande, por lo que el equipo de React optimizó el algoritmo para lograr una complejidad O (n) para comparar las diferencias.
La clave para lograr la complejidad O(n) es comparar solo nodos dentro del mismo nivel, en lugar de entre niveles, ya que en el mundo real los elementos DOM rara vez se mueven entre niveles.
El algoritmo de diferenciación DOM virtual se divide en 2 pasos:
En la comparación del algoritmo de diferenciación real, hay 5 reglas principales para la comparación de nodos.
Parte del El código fuente/ vuejs/vue/blob/8a219e3d4cfc580bbb3420344600801bd9473390/src/ core/vdom/patch.js#L501 es el siguiente:
En las entradas de la función reconcileChildren
Los dos cuerpos de diff son: oldFiber (current.child) y newChildren (nextChildren, new ReactElement), estas son dos estructuras de datos diferentes.
Parte del código fuente
Por lo general, la optimización manual de dom es más efectiva que la dom virtual. No hay ningún problema en optimizar manualmente una estructura DOM simple, pero cuando la estructura de la página es muy grande y compleja, la optimización manual llevará mucho tiempo, la mantenibilidad no es alta y no hay garantía de que todos tengan la capacidad de optimizar manualmente. Por lo tanto, surgieron soluciones de directorio virtual.
Virtual dom es una solución para "resolver el impacto en el rendimiento de demasiados domos en funcionamiento".
Una máquina virtual generalmente no es la mejor práctica, pero es versátil y logra un equilibrio entre eficiencia y mantenibilidad.
El significado de virutal dom:
La diferencia de vue2.x se encuentra en el archivo patch.js. El algoritmo se deriva de snabbdom y tiene una complejidad de O (n). . Comprender el proceso de diferenciación nos permite utilizar el marco de manera más eficiente. Las diferencias en React son básicamente las mismas que las diferencias en vue.
La diferencia de vue2.x se encuentra en el archivo patch.js.
El punto más importante es que las comparaciones sólo se realizan dentro del mismo nivel, no entre niveles.
Comparación de antes y después: es posible que desees ir directamente después
ya que se trata de una práctica recomendada.
Pero la operación de diferenciación real es:
El algoritmo de diferenciación también se usa en Vue, por lo que es muy importante comprender cómo funciona Vue.
A través de esta pregunta, podemos comprender bien dónde se encuentra el algoritmo diff en todo el proceso de compilación, qué parte es, qué operaciones realiza y cuál es el resultado después de usar el algoritmo diff.
Explicación:
La función de montaje obtiene la plantilla y luego va a la función compileToFunctions.
La función CompileToFunctions compila la plantilla en una función de renderizado. Primero, lee el caché y, si no hay caché, llama al método de compilación para obtener la función de representación como una cadena y luego genera la función de representación en una nueva función.
La función de compilación compila la plantilla en un formato de cadena que representa la función. Nos centraremos en el renderizado más adelante.
Una vez que hayamos terminado de generar el método de renderizado, pasaremos al montaje para las actualizaciones de DOM. La lógica central de este método es la siguiente:
La compilación mencionada anteriormente compila la plantilla en una cadena que representa la función. El código principal es el siguiente:
La función de compilación tiene tres pasos principales:
Generar un archivo que contiene
Función de análisis: su función principal es analizar el cadena de plantilla en AST (árbol de sintaxis abstracta). La función de análisis convierte la estructura de la plantilla (directivas, atributos, etiquetas) en un AST, la almacena en un ASTElement y luego la analiza para producir un AST.
Función de optimización (src/compiler/optomizer.js): La función principal es convertir cadenas de plantilla en AST (Árbol de sintaxis abstracta). La función principal es marcar nodos estáticos. Esto se hará más adelante durante el proceso de parcheo comparando las estructuras de árbol de VNode nuevas y antiguas. En el algoritmo de diferencia, los nodos marcados como estáticos se ignoran y no se realiza ninguna comparación detallada.
Función Generar (src/compiler/codegen/index.js): Su función principal es generar cadenas para renderizar funciones basadas en la estructura AST.
La función genElement (src/compiler/codgen/index.js) llama a diferentes métodos basados en las propiedades del AST para generar la cadena a devolver.
En resumen:
Se presentan los tres pasos principales de la compilación de funciones.
La función de parche es una función de diferenciación que compara VNodes antiguos y nuevos. Su propósito es optimizar el dom y minimizar las operaciones en el dom a través de algoritmos. El objetivo de optimización del algoritmo snabbdom es agregar o eliminar menos nodos en cada nivel de manipulación DOM, y solo lo hará dentro del mismo nivel, sin comparar entre niveles.
En resumen:
Esta optimización se combina con el algoritmo Diff para determinar el tipo de VNode en el momento de la creación y utiliza operaciones de bits para determinar el VNode durante el tipo de proceso de montaje/parche. , mejorando así el rendimiento.
Consulte el código fuente de vue3.x:/vuejs/vue/blob/8a219e3d4cfc580bbb3420344600801bd9473390/src/core/vdom/patch.js
Comparación de fibra antigua y fibra nueva Comparación de Los nuevos nodos ReactElement generarán nuevos nodos de fibra, etiquetados con effectTag, y estos nodos se adjuntarán al árbol workInProgress como nuevos nodos WIP. De esta manera, la estructura del árbol del proceso de trabajo se define poco a poco y básicamente se determinan los nuevos nodos del proceso de trabajo. Una vez completado el cambio de base, se completa el nodo de inicio de trabajo del nodo de trabajo en progreso y el siguiente paso es la etapa de trabajo completo.
Algoritmo snabbdom: /snabbdom/snabbdom
Posicionamiento: Biblioteca DOM virtual, centrándose en la simplicidad, modularidad, funcionalidad y rendimiento.
Tipo de Vnode definido en snabbdom (/snabbdom/snabbdom/blob/27e9c4d5dca62b6dabf9ac23efb95f1b6045b2df/src/vnode.ts#L12)
Dirección de la función init:
El dirección de la función inicial.
/snabbdom/snabbdom/blob/27e9c4d5dca62b6dabf9ac23efb95f1b6045b2df/src/init.ts#L63
La función init() toma como parámetros una matriz de módulos y un objeto domApi opcional. Devuelve una función, la función patch().
La interfaz del objeto domApi contiene muchos métodos para la manipulación DOM.
Fuente:
/snabbdom/snabbdom/blob/27e9c4d5dca62b6dabf9ac23efb95f1b6045b2df/src/init.ts#L367
Fuente:
/snabbdom Función / snabbdom/blob/blob/patch(). snabbdom/blob/27e9c4d5dca62b6dabf9ac23efb95f1b6045b2df/src/h.ts#L33
La función h() recibe varios parámetros, uno de los cuales debe ser el parámetro sel. Su función es montar el contenido del nodo en el. contenedor y devuelve un nuevo VNode.
En vue2.x, no utilizamos el algoritmo snabbdom completo, pero hicimos algunas modificaciones y optimizaciones basadas en los escenarios de aplicación de vue, principalmente en el juicio de palabras clave y diferencias.
1. En snabbdom, key y sel se utilizan para determinar si los nodos son iguales. Por lo tanto, en vue, para satisfacer la equivalencia de claves, se agregan algunos juicios adicionales y también se juzgarán. si los nombres de las etiquetas son los mismos, si es un nodo de anotación, si es un nodo asincrónico o si es del mismo tipo cuando se ingresa, etc.
/vue2.x no es exactamente tramposo.
/vuejs/vue/blob/8a219e3d4cfc580bbb3420344600801bd9473390/src/core/vdom/patch.js#L35
2. diff, patchVnode es una función que compara los cambios de plantilla y se puede utilizar diferenciar o actualizar directamente.
/vuejs/vue/blob/8a219e3d4cfc580bbb3420344600801bd9473390/src/core/vdom/patch.js#L404