De documentos:
detectChanges (): void
Comprueba el detector de cambios y sus elementos secundarios.
Es decir, si hay un caso en el que algo dentro de su modelo (su clase) ha cambiado pero no ha reflejado la vista, es posible que deba notificar a Angular para detectar esos cambios (detectar cambios locales) y actualizar la vista.
Los posibles escenarios pueden ser:
1- El detector de cambio se separa de la vista (ver separación )
2- Ha ocurrido una actualización pero no ha estado dentro de la Zona Angular, por lo tanto, Angular no lo sabe.
Como cuando una función de terceros ha actualizado su modelo y desea actualizar la vista después de eso.
someFunctionThatIsRunByAThirdPartyCode(){
yourModel.text = "new text";
}
Debido a que este código está fuera de la zona de Angular (probablemente), lo más probable es que necesite asegurarse de detectar los cambios y actualizar la vista, por lo tanto:
myFunction(){
someFunctionThatIsRunByAThirdPartyCode();
// Let's detect the changes that above function made to the model which Angular is not aware of.
this.cd.detectChanges();
}
NOTA :
Hay otras formas de hacer que el trabajo anterior funcione, en otras palabras, hay otras formas de llevar ese cambio al ciclo de cambio angular.
** Podría incluir esa función de terceros dentro de una zona. Ejecutar:
myFunction(){
this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
}
** Podrías envolver la función dentro de un setTimeout:
myFunction(){
setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
}
3- También hay casos en los que actualiza el modelo una vez change detection cycle
que finaliza, en los que obtiene este temido error:
"La expresión ha cambiado después de que se verificó";
Esto generalmente significa (del lenguaje Angular2):
Vi un cambio en su modelo que fue causado por una de mis formas aceptadas (eventos, solicitudes XHR, setTimeout y ...) y luego ejecuté mi detección de cambios para actualizar su vista y terminé, pero luego hubo otra funciona en su código que actualizó el modelo nuevamente y no quiero volver a ejecutar mi detección de cambios porque ya no hay una comprobación sucia como AngularJS: D y ¡deberíamos usar un flujo de datos unidireccional!
Definitivamente te encontrarás con este error: P.
Un par de formas de solucionarlo:
1- Forma correcta : asegúrese de que la actualización esté dentro del ciclo de detección de cambios (las actualizaciones de Angular2 son unidireccionales que ocurren una vez, no actualice el modelo después de eso y mueva su código a un lugar / hora mejor).
2- Manera perezosa : ejecuta detectChanges () después de esa actualización para hacer feliz a angular2, esta definitivamente no es la mejor manera, pero como preguntaste cuáles son los posibles escenarios, esta es una de ellas.
De esta manera estás diciendo: Sinceramente sé que ejecutaste la detección de cambios, pero quiero que lo vuelvas a hacer porque tuve que actualizar algo sobre la marcha después de que terminaste la comprobación.
3- Pon el código dentro de a setTimeout
, porque setTimeout
está parcheado por zona y se ejecutará detectChanges
después de que haya terminado.
De los documentos
markForCheck() : void
Marca todos los antepasados ChangeDetectionStrategy como para comprobarlos.
Esto se necesita principalmente cuando ChangeDetectionStrategy de su componente es OnPush .
OnPush en sí mismo significa, solo ejecuta la detección de cambios si alguno de estos ha sucedido:
1- Una de las entradas @ del componente se ha reemplazado completamente con un nuevo valor, o simplemente, si la referencia de la propiedad @Input ha cambiado por completo.
Entonces, si ChangeDetectionStrategy de su componente es OnPush y luego tiene:
var obj = {
name:'Milad'
};
Y luego lo actualizas / mutas como:
obj.name = "a new name";
Esto no actualizará la referencia obj , por lo tanto, la detección de cambios no se ejecutará, por lo tanto, la vista no refleja la actualización / mutación.
En este caso, debe indicarle manualmente a Angular que verifique y actualice la vista (markForCheck);
Entonces, si hiciste esto:
obj.name = "a new name";
Usted necesita hacer ésto:
this.cd.markForCheck();
Por el contrario, a continuación causaría que se ejecutara una detección de cambio:
obj = {
name:"a new name"
};
Que reemplazó por completo el obj anterior con uno nuevo {}
;
2- Se ha disparado un evento, como un clic o algo así o cualquiera de los componentes secundarios ha emitido un evento.
Eventos como:
- Hacer clic
- Tecla Arriba
- Eventos de suscripción
- etc.
En resumen:
Úselo detectChanges()
cuando haya actualizado el modelo después de que angular haya ejecutado su detección de cambios, o si la actualización no ha estado en el mundo angular en absoluto.
Úselo markForCheck()
si está usando OnPush y está pasando ChangeDetectionStrategy
por alto al mutar algunos datos o si ha actualizado el modelo dentro de un setTimeout ;