Con respecto a la descripción de los indicadores de rendimiento del front-end, la industria tiene sus propias opiniones. En resumen, está relacionado con el rendimiento de la primera pantalla y la fluidez de la página. Analizar la perspectiva de la fluidez de la página. [Recomendación de tutorial relacionado: "Tutorial angular"]
¿Qué es la fluidez de la página?
La fluidez de la página está determinada por la velocidad de fotogramas FPS (fotogramas por segundo: fotogramas transmitidos por segundo). Generalmente, la frecuencia de actualización de la pantalla de los navegadores convencionales es de 60 Hz (se actualiza 60 veces por segundo) y la frecuencia de fotogramas óptima es 60 FPS. Cuanto mayor sea la velocidad de fotogramas, más fluida será la página. 60 Hz significa que la pantalla se actualizará cada 16,6 ms, lo que significa que la representación de cada página debe completarse en 16,6 ms; de lo contrario, la página perderá fotogramas y se congelará.根因在于:浏览器中的JavaScript 执行和页面渲染会相互阻塞
.
En las herramientas de desarrollo de Chrome, podemos ejecutar Cmd+Shift+P e ingresar show fps para abrir rápidamente el panel de fps, como se muestra en la siguiente figura:
Al observar el panel de FPS, podemos monitorear fácilmente la fluidez de la página actual.
1 Factores que afectan el rendimiento de la página
Si la interacción de la página es fluida depende de si la respuesta de la página es fluida, y la respuesta de la página es esencialmente el proceso de volver a representar los cambios en el estado de la página en la página.
El proceso de respuesta de la página es aproximadamente el siguiente:
Generalmente, la lógica de procesamiento de eventos del controlador de eventos no consume demasiado tiempo, por lo que los factores que afectan el rendimiento de Angular radican principalmente en异步事件触发
y变更检测
. Generalmente, la lógica de procesamiento de eventos del controlador de eventos no consume demasiado tiempo, por lo que los factores que afectan el rendimiento de Angular radican principalmente en la activación de eventos asincrónicos y la detección de cambios.
Para Angular, el proceso de representación de la página es el proceso de detección de cambios. Se puede entender que la detección de cambios de Angular debe completarse en 16,6 ms para evitar la pérdida y el retraso del marco de la página.
El rendimiento de la respuesta de la página se puede optimizar desde los siguientes tres aspectos.
(1) Para la etapa de evento de activación, la activación de eventos asincrónicos se puede reducir para reducir el número total de detecciones de cambios y re-presentación
(2) Para la etapa de lógica de ejecución del Controlador de eventos, el tiempo de ejecución se puede reducir optimizando el complejo; lógica de código
(3) Para la fase de enlace de datos de detección de cambios y actualización de DOM, la cantidad de cálculos de detección de cambios y datos de plantilla se puede reducir para reducir el tiempo de representación
para (2) el controlador de eventos, los problemas específicos deben analizarse en; Se detalla y no se centrará principalmente en (1) (3) ) Optimización
2 Plan de optimización
2.1 Reducir la activación de eventos asincrónicos
Angular En el modo de detección de cambios predeterminado, los eventos asincrónicos activarán la detección de cambios globales. Mejorará enormemente el rendimiento de Angular.
Los eventos asincrónicos incluyen eventos de macrotarea y eventos de microtarea.
La optimización de eventos asincrónicos es principalmente para eventos de escucha de documentos. Por ejemplo, escuche clic, mouseup, mousemove... y otros eventos en el documento.
Escenario de evento de escucha:
Renderer2.listen(document,…)
fromEvent(document,…)
document.addEventListener(…)
El evento de escucha DOM debe eliminarse cuando no es necesario activarlo.
Por ejemplo: escenarios de uso del comando del cuadro de aviso [pop]
: filtrar columnas de la tabla, hacer clic en algún lugar que no sea el ícono o desplazarse por la página, ocultar el cuadro emergente de filtro de columna.
El método anterior era monitorear directamente el evento de clic y el evento de desplazamiento
.del documento en el comando pop de esta manera: El único inconveniente es que no se muestra el cuadro de aviso, pero todavía hay eventos de monitoreo, lo cual es muy irrazonable.
Solución razonable: solo escuche los eventos de clic y desplazamiento cuando se muestre el cuadro de aviso y elimine los eventos de escucha cuando esté oculto.
Para eventos de escucha DOM activados con frecuencia, puede utilizar operadores rjx para optimizar los eventos. Consulte Operadores Rjx para obtener más detalles. Canicas RxJS.
2.2 Detección de cambios
¿Qué es la detección de cambios?
Para comprender la detección de cambios, podemos buscar respuestas a partir de los objetivos de la detección de cambios. El objetivo de la detección de cambios angulares es mantener sincronizados el modelo (código TypeScript) y la plantilla (HTML). Por lo tanto, la detección de cambios puede entenderse como: detectar cambios en el modelo y actualizar la plantilla ( DOM ) al mismo tiempo .
¿Qué es el proceso de detección de cambios?
Al realizar la detección de cambios en orden de arriba hacia abajo en el árbol de componentes, es decir, la detección de cambios se realiza primero en el componente principal y luego en los componentes secundarios. Primero verifique los cambios de datos del componente principal y luego actualice la plantilla del componente principal. Al actualizar la plantilla, cuando encuentre el componente secundario, actualizará el valor vinculado al componente secundario y luego ingresará el componente secundario para ver si. El índice del valor de entrada @Input ha cambiado. Si cambia, marque el subcomponente como sucio, lo que requiere una detección de cambios posterior. Después de marcar el subcomponente, continúe actualizando la plantilla detrás del subcomponente en el componente principal. se han actualizado, realice cambios en el subcomponente de detección.
2.2.1 Principio de detección de cambios angulares
En el modo predeterminado de detección de cambios predeterminado, el principio de los eventos asincrónicos que desencadenan la detección de cambios de Angular es que angular llama al método tick() de ApplicationRef cuando procesa eventos asincrónicos usando Zone.js para ejecutar desde el componente raíz. al subcomponente Detección de cambios. Durante el proceso de inicialización de la aplicación Angular, se crea una instancia de una zona (NgZone) y luego toda la lógica se ejecuta en el objeto _inner del objeto.
Zone.js implementa las siguientes clases:
El principio del proceso de detección es aproximadamente el siguiente:
las operaciones del usuario desencadenan eventos asincrónicos (por ejemplo: eventos DOM, solicitudes de interfaz...)
=> La clase ZoneTask maneja los eventos. El método runTask() de zona se llama en la función invokeTask() En el método runTask, zona pasa el atributo de instancia _zoneDelegate y llama al enlace de ZoneSpec
=> los tres enlaces de ZoneSpec (onInvokeTask, onInvoke, onHasTask) pasan el checkStable. () Función Activador de notificación Zone.onMicrotaskEmpty.emit(null)
=> El componente raíz llama a tick() después de escuchar onMicrotaskEmpty, y llama detectChanges()
en el método tick para iniciar la detección desde el componente raíz
=> ··· refreshView()
llama executeTemplate()
, en el método executeTemplate
Llame templateFn()
para actualizar el valor vinculado a la plantilla y al subcomponente (这时候会去检测子组件的
输入引用是否改变,如果有改变,会将子组件标记为
Sucio ,也就是该子组件需要变更检测
)
Diagrama de flujo detallado del principio de detección de cambios:
Simplifique el proceso:
active un evento asincrónico
=> ZoneTask maneja el evento
=> ZoneDelegate llama al gancho ZoneSpec para activar la notificación onMicrotaskEmpty
=> el componente raíz recibe la notificación onMicrotaskEmpty, ejecuta tick() y comienza a detectar y actualizar el dom
Como se puede ver en el código anterior,当微任务为空的时候才会触发变更检测
.
Diagrama de flujo del principio de detección de cambios simple:
Análisis de código fuente angular Blog de referencia de Zone.js.
2.2.2 Solución de optimización de la detección de cambios
1) Utilice
el principio del modo OnPush: reduzca el tiempo que lleva una detección de cambios.
La diferencia entre el modo OnPush y el modo predeterminado es que los eventos de escucha DOM, los eventos de temporizador y las promesas no activarán la detección de cambios. El estado del componente en el modo predeterminado es siempre CheckAlways, lo que significa que el componente debe probarse en cada ciclo de detección.
En modo OnPush: Las siguientes situaciones activarán la detección de cambios
S1 y la referencia @Input del componente a cambiar.
S2. Eventos vinculados al DOM del componente, incluidos eventos vinculados al DOM de sus subcomponentes, como hacer clic, enviar y presionar el mouse. @HostListener()
Nota:
Los eventos DOM monitoreados a través de renderer2.listen() no activarán la detección de cambios.
El método de escucha nativo de dom.addEventListener() no activará la detección de cambios
S3 y los eventos de suscripción observables también están configurados. al mismo tiempo.
S4 Utilice los siguientes métodos para activar manualmente la detección de cambios:
ChangeDetectorRef.detectChanges(): activa la detección de cambios para el componente actual y los subcomponentes que no son OnPush.
ChangeDetectorRef.markForCheck(): marca la vista actual y todos sus antepasados como sucios y la detección se activará en el siguiente ciclo de detección.
ApplicationRef.tick(): No activará la detección de cambios
2)
Principio de uso de NgZone.runOutsideAngular(): Reduzca la cantidad de detecciones de cambios
y escriba el monitoreo de eventos dom global en la devolución de llamada del método NgZone.runOutsideAngular() El evento dom. no activa la detección de cambios angulares. Si el componente actual no se ha actualizado, puede ejecutar el gancho detectChanges() de ChangeDetectorRef en la función de devolución de llamada para activar manualmente la detección de cambios del componente actual.
Ejemplo: componente de icono dinámico app-icon-react
2.2.3 Método de depuración
1: puede utilizar el complemento Angular DevTools en la consola del navegador para ver un determinado evento DOM y el estado de detección de angular:
Método 2: puede ingresar directamente: ng.profiler.timeChangeDetection() en la consola para ver el tiempo de detección. Este método puede ver el tiempo de detección global. Blog de referencia Creación de perfiles Detección de cambios angulares
2.3 Optimización de plantilla (HTML)
2.3.1 Reducir la representación DOM: ngFor más trackBy
Usando el atributo trackBy de *ngFor, Angular solo cambia y vuelve a representar las entradas modificadas sin tener que recargar toda la lista de entradas.
Por ejemplo: escenario de clasificación de tablas. Si se agrega trackBy a ngFor, solo los elementos dom de la fila se moverán cuando se represente la tabla. Si no se agrega trackBy, los elementos dom de la tabla existentes se eliminarán primero y luego se agregarán los elementos dom de la fila. Obviamente el rendimiento de mover sólo elementos dom será mucho mejor.
2.3.2 No use funciones en expresiones de plantilla.
No use llamadas a funciones en expresiones de plantilla angular. En su lugar, puede usar una tubería o puede usar una variable después del cálculo manual. Cuando se utilizan funciones en plantillas, independientemente de si el valor ha cambiado o no, la función se ejecutará cada vez que se realice la detección de cambios, lo que afectará el rendimiento.
Escenarios para usar funciones en plantillas:
2.3.3 Reducir el uso de ngFor
El uso de ngFor afectará el rendimiento cuando la cantidad de datos sea grande.
Ejemplo:
usando ngFor:
Sin usar ngFor: el rendimiento mejoró aproximadamente 10 veces