Te damos la bienvenida a nuestra comunidad, en este lugar vas a encontrar la respuesta que buscabas.
Solución:
De los documentos:
detectChanges (): void
Comprueba el detector de cambios y sus hijos.
Significa que, 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 cambios se separa de la vista (ver separar)
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 deba asegurarse de detectar los cambios y actualizar la vista, así:
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 funcione lo anterior, en otras palabras, hay otras formas de llevar ese cambio dentro del ciclo de cambio angular.
** Podría envolver esa función de terceros dentro de una zona.
myFunction()
this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
** Puede envolver la función dentro de un setTimeout:
myFunction()
setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
3- También hay casos en los que actualiza el modelo después de la change detection cycle
está terminado, donde en esos casos aparece 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 lo terminé, pero luego hubo otro función en su código que actualizó el modelo nuevamente y no quiero ejecutar mi detección de cambios nuevamente porque ya no hay verificación sucia como AngularJS: D ¡y deberíamos usar el flujo de datos unidireccional!
Definitivamente te encontrarás con este error: P.
Un par de formas de solucionarlo:
1- Forma apropiada : asegúrese de que la actualización esté dentro del ciclo de detección de cambios (las actualizaciones de Angular2 son un flujo de una vía que ocurre una vez, no actualice el modelo después de eso y mueva su código a un lugar / tiempo mejor).
2- Manera perezosa: ejecuta detectChanges () después de esa actualización para hacer feliz a angular2, definitivamente esta no es la mejor manera, pero como preguntaste cuáles son los posibles escenarios, este es uno de ellos.
De esta manera, está diciendo: sé sinceramente que ejecutó la detección de cambios, pero quiero que lo haga nuevamente porque tuve que actualizar algo sobre la marcha después de que terminó la verificación.
3- Pon el código dentro de un setTimeout
, porque setTimeout
está parcheado por zona y se ejecutará detectChanges
después de que haya terminado.
De los documentos
markForCheck() : void
Marca a todos los antepasados de ChangeDetectionStrategy para que se verifiquen.
Esto es principalmente necesario cuando el ChangeDetectionStrategy de su componente es OnPush.
OnPush en sí significa, solo ejecutar la detección de cambios si ha sucedido alguno de estos:
1- Una de las @inputs del componente ha sido reemplazada por completo con un nuevo valor, o simplemente, si la referencia de la propiedad @Input ha cambiado por completo.
Así que si ChangeDetectionStrategy de su componente es OnPush y luego tienes:
var obj =
name:'Milad'
;
Y luego lo actualizas / mutas como:
obj.name = "a new name";
Esto no actualizará el obj referencia, 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 decirle 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();
Más bien, a continuación, se ejecutaría una detección de cambios:
obj =
name:"a new name"
;
Que reemplazó completamente el obj anterior con un 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.
Así que en resumen:
-
Usar
detectChanges()
cuando haya actualizado el modelo después de que angular se haya ejecutado, su detección de cambio, o si la actualización no ha estado en el mundo angular en absoluto. -
Usar
markForCheck()
si está usando OnPush y está omitiendo elChangeDetectionStrategy
mutando algunos datos o ha actualizado el modelo dentro de un setTimeout;
La mayor diferencia entre los dos es que detectChanges()
realmente activa la detección de cambios, mientras que markForCheck()
no activa la detección de cambios.
detectChanges
Este se usa para ejecutar la detección de cambios para el árbol de componentes comenzando con el componente que desencadena detectChanges()
sobre. Entonces, la detección de cambios se ejecutará para el componente actual y todos sus elementos secundarios. Angular contiene referencias al árbol del componente raíz en el ApplicationRef
y cuando ocurre cualquier operación asincrónica, activa la detección de cambios en este componente raíz a través de un método contenedor tick()
:
@Injectable()
export class ApplicationRef_ extends ApplicationRef {
...
tick(): void {
if (this._runningTick)
throw new Error('ApplicationRef.tick is called recursively');
const scope = ApplicationRef_._tickScope();
try {
this._runningTick = true;
this._views.forEach((view) => view.detectChanges()); <------------------
view
aquí está la vista del componente raíz. Puede haber muchos componentes raíz como describí en ¿Cuáles son las implicaciones de arrancar múltiples componentes?
@milad describió las razones por las que 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 vista a ChecksEnabled
. Aquí está el código fuente:
export function markParentViewsForCheck(view: ViewData)
let currView: ViewData
La detección de cambio real para el componente no está programada, pero cuando ocurra en el futuro (ya sea como parte del ciclo de CD actual o siguiente), las vistas del componente principal se comprobarán incluso si tenían detectores de cambios separados. Los detectores de cambio se pueden desconectar utilizando cd.detach()
o especificando OnPush
estrategia de detección de cambios. Todos los controladores de eventos nativos marcan todas las vistas de componentes principales para su verificación.
Este enfoque se utiliza a menudo en ngDoCheck
gancho del ciclo de vida. Puedes leer más en el Si piensas ngDoCheck
significa que 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.
cd.detectChanges()
ejecutará la detección de cambios inmediatamente desde el componente actual hasta sus descendientes.
cd.markForCheck()
no ejecutará la detección de cambios, pero marcará a sus antepasados como necesarios para 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.
- Si desea reducir el número de veces que la detección de cambios se denomina uso
cd.markForCheck()
. A menudo, los cambios afectan a varios componentes y en algún lugar se llamará la detección de cambios. Básicamente estás diciendo: asegurémonos de que este componente esté además actualizado cuando eso suceda. (La vista se actualiza inmediatamente en todos los proyectos que he escrito, pero no en todas las pruebas unitarias). - Si no puedes estar seguro de que
cd.detectChanges()
no es en la actualidadcorriendo detección de cambios, usocd.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 las suposiciones en torno a las cuales está diseñada la detección de cambios de Angular. - Si es fundamental que la vista se actualice sincrónicamente antes de alguna otra acción, utilice
detectChanges()
.markForCheck()
puede que no actualice su vista a tiempo. La prueba unitaria de algo afecta su vista, por ejemplo, puede requerir que llame manualmentefixture.detectChanges()
cuando eso no era necesario en la propia aplicación. - Si está cambiando el estado en un componente con más ancestros que descendientes, puede obtener un aumento de rendimiento usando
detectChanges()
ya que no está ejecutando innecesariamente la detección de cambios en los antepasados del componente.
Si te animas, eres capaz de dejar un tutorial acerca de qué le añadirías a esta noticia.