¿Cuál es la diferencia entre ChangeDetectorRef.markForCheck()
y ChangeDetectorRef.detectChanges()
?
Solo encontré información sobre SO en cuanto a la diferencia entre NgZone.run()
, pero no entre estas dos funciones.
Para obtener respuestas con solo una referencia al documento, ilustre algunos escenarios prácticos para elegir uno sobre el otro.
angular
angular2-changedetection
parlamento
fuente
fuente
Respuestas:
De documentos:
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.
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:
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:
** Podrías envolver la función dentro de un setTimeout:
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
, porquesetTimeout
está parcheado por zona y se ejecutarádetectChanges
después de que haya terminado.De los documentos
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:
Y luego lo actualizas / mutas como:
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:
Usted necesita hacer ésto:
Por el contrario, a continuación causaría que se ejecutara una detección de cambio:
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:
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á pasandoChangeDetectionStrategy
por alto al mutar algunos datos o si ha actualizado el modelo dentro de un setTimeout ;fuente
detectChanges
Vista de actualizaciones. Vea esta explicación detallada .this.cdMode === ChangeDetectorStatus.Checked
no actualiza la vista, es por eso que usaría markForCheck.detectChanges
. Y no haycdMode
en Angular4.x.x
. Escribo sobre eso en mi artículo. Me alegra que te haya gustado. No olvides que puedes recomendarlo en medio o seguirme :)La mayor diferencia entre los dos es que en
detectChanges()
realidad activa la detección de cambios, mientrasmarkForCheck()
que no activa la detección de cambios.detectChanges
Este se usa para ejecutar la detección de cambios para el árbol de componentes que comienza con el componente que activa
detectChanges()
. Por lo tanto, la detección de cambios se ejecutará para el componente actual y todos sus elementos secundarios. Angular contiene referencias al árbol de componentes raíz enApplicationRef
y cuando ocurre cualquier operación asíncrona, activa la detección de cambios en este componente raíz a través de un método de envolturatick()
:view
Aquí está la vista del componente raíz. Puede haber muchos componentes raíz como lo describí en ¿Cuáles son las implicaciones de arrancar múltiples componentes ?@milad describió las razones por las cuales potencialmente podría necesitar activar la detección de cambios manualmente.
markForCheck
Como dije, este tipo no activa la detección de cambios en absoluto. Simplemente va hacia arriba desde el componente actual al componente raíz y actualiza su estado de visualización
ChecksEnabled
. Aquí está el código fuente:La detección de cambio real para el componente no está programada, pero cuando sucederá en el futuro (ya sea como parte del ciclo de CD actual o siguiente), las vistas del componente principal se verificarán incluso si se han desconectado los detectores de cambio. Los detectores de cambio se pueden separar usando
cd.detach()
o especificando laOnPush
estrategia de detección de cambio. Todos los controladores de eventos nativos marcan todas las vistas de componentes principales para su verificación.Este enfoque se usa a menudo en el
ngDoCheck
gancho del ciclo de vida. Puede leer más en Si cree quengDoCheck
su componente está siendo revisado, lea este artículo .Consulte también Todo lo que necesita saber sobre la detección de cambios en Angular para obtener más detalles.
fuente
markForCheck
. Entonces, si no está utilizando una tubería asíncrona, probablemente sea lo que debería usar. Sin embargo, tenga en cuenta que la actualización de la tienda debe ocurrir como resultado de algún evento asíncrono para que comience la detección de cambios. Ese es siempre el caso. Pero hay excepciones blog.angularindepth.com/…async pipe
ya que dentro de la suscripción generalmente tenemos algunas cosas que hacercall setFromValues
do some comparison
... y siasync
se llamamarkForCheck
¿cuál es el problema si lo llamamos nosotros mismos? pero, de nuevo, generalmente tenemos 2-3 o, a veces, más selectores parangOnInit
obtener datos diferentes ... y los llamamosmarkForCheck
a todos ... ¿está bien?cd.detectChanges()
ejecutará la detección de cambios inmediatamente desde el componente actual hacia abajo a través de sus descendientes.cd.markForCheck()
no ejecutará la detección de cambios, pero marcará a sus antepasados como la necesidad de ejecutar la detección de cambios. La próxima vez que la detección de cambios se ejecute en cualquier lugar, también se ejecutará para aquellos componentes que fueron marcados.cd.markForCheck()
. A menudo, los cambios afectan a múltiples componentes y en algún lugar se llamará la detección de cambios. Básicamente estás diciendo: solo asegurémonos de que este componente también se actualice cuando eso suceda. (La vista se actualiza inmediatamente en cada proyecto que he escrito, pero no en todas las pruebas unitarias).cd.detectChanges()
no se está ejecutando la detección de cambios, usecd.markForCheck()
.detectChanges()
error en ese caso. Esto probablemente significa que está tratando de editar el estado de un componente ancestro, que está trabajando en contra de los supuestos en torno a los cuales se diseñó la detección de cambios de Angular.detectChanges()
.markForCheck()
Es posible que no actualice su vista a tiempo. La prueba de unidad que afecta algo a su vista, por ejemplo, puede requerir que llame manualmentefixture.detectChanges()
cuando eso no era necesario en la propia aplicación.detectChanges()
ya que no está ejecutando innecesariamente la detección de cambios en los antepasados del componente.fuente