angularjs - navigate - La detección de cambios no funciona correctamente en el componente ng2 después de la navegación a través de angular1 ui-router
router.navigate angular 5 (1)
En una aplicación que usa ng-upgrade para usar algunos nuevos componentes ng2 (V2.2.4) dentro de una aplicación ng1 (V1.5.9) grande (usando ui-router), actualmente estoy viendo un extraño problema de detección de cambios. Por lo que puedo decir, esto se ha introducido en algunas actualizaciones de ng2, pero lamentablemente no puedo verificarlo fácilmente.
Lo he reducido a un ejemplo mínimo por ahora donde simplemente tengo este componente:
@Component({
selector:''my-ng2-demo'',
template: ''<div>{{status}}</div>''
})
export class MyNg2Demo implements OnDestroy {
public status:boolean = true;
private interval:any;
constructor() {
this.interval = setInterval(() => {
this.status = !this.status;
console.log(''status: '' + this.status);
}, 2000);
}
ngOnDestroy():void {
clearInterval(this.interval);
}
}
Ese componente se actualiza en el adaptador de actualización y se registra como un componente de entrada en el módulo.
El componente se usa en la plantilla de un controlador ng1 como este:
<my-ng2-demo></my-ng2-demo>
Cuando abro un navegador y navego directamente a esa página (la ruta del controlador ng1) todo funciona como se esperaba: el ui muestra verdadero / falso alternando cada 2 segundos.
Sin embargo, cuando navego lejos y luego vuelvo a la página (visitando algunas rutas diferentes), de repente la detección de cambio no parece funcionar. El valor visualizado se alterna solo cada 5-6 segundos, parece bastante aleatorio, aunque en la consola todavía veo los valores esperados.
Cuando cambio el constructor del componente a este:
constructor(private zone: NgZone) {
this.interval = setInterval(() => {
zone.run(() => {
this.status = !this.status;
console.log(''status: '' + this.status);
});
}, 2000);
}
De repente funciona de nuevo.
Obviamente, esta no es una solución factible ya que el comportamiento que estoy viendo en la aplicación real es mucho más complejo (tendría que agregar zone.run
en docenas de lugares probablemente, lo cual no sería zone.run
).
Lo he depurado durante horas y no entiendo lo que está sucediendo. En el generador de perfiles de JavaScript de Chrome, básicamente veo que la página permanece inactiva durante casi todo el tiempo en esos 5-6 segundos en los que no sucede nada.
Esta no es una captura de pantalla de ese componente de demostración (pero básicamente tiene el mismo aspecto), sino del perfil del componente de pestaña que estaba probando inicialmente (el cambio de pestañas se realizó igual de largo sin acciones visibles entre medio).
actualizar:
Después de un poco más de experimentación, lo que encuentro bastante sorprendente también es que cuando en lugar de poner el código de cambio de estado en una llamada zone.run
, agrego una llamada a ApplicationRef.tick()
(como se menciona aquí, por ejemplo: https: // stackoverflow.com/a/34829089/1335619 ) tampoco funciona en absoluto. No entiendo por qué forzar una aplicación completa de detección de cambios no hace nada, pero una llamada ejecutada por zonas funciona de alguna manera.
Código de ejemplo con tic llamada que no funciona:
constructor(private applicationRef:ApplicationRef) {
this.interval = setInterval(() => {
this.status = !this.status;
console.log(''status: '' + this.status);
applicationRef.tick();
}, 2000);
}
Hay un error en la versión angular que está utilizando. La detección de cambios no funciona como debería en aplicaciones actualizadas ng.
Consulte https://github.com/angular/angular/issues/12318 para obtener más detalles.
Si actualiza a 2.4.4, debería resolver el problema.