Ответ 1
В версии Angular есть ошибка. Обнаружение изменений не работает должным образом в ng-обновленных приложениях.
Подробнее см. https://github.com/angular/angular/issues/12318.
Если вы обновляете до 2.4.4, это должно решить проблему.
В приложении, использующем ng-upgrade, чтобы использовать некоторые новые компоненты ng2 (V2.2.4) внутри большого приложения ng1 (V1.5.9) (с использованием ui-router), в настоящее время я вижу очень странную проблему обнаружения изменений. Насколько я могу судить, это было внесено в некоторое обновление ng2, но, к сожалению, я не могу легко проверить, что в настоящее время.
Я сократил его до минимального примера, теперь, когда у меня просто есть этот компонент:
@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);
}
}
Этот компонент обновлен в адаптере обновления и зарегистрирован как компонент входа в модуле.
Компонент используется в шаблоне контроллера ng1 следующим образом:
<my-ng2-demo></my-ng2-demo>
Когда я открываю браузер и перехожу непосредственно на эту страницу (маршрут контроллера ng1), все работает так, как ожидалось: ui показывает, что true/false чередуются каждые 2 секунды.
Однако: когда я перемещаюсь, а затем возвращаюсь на страницу (посещая несколько разных маршрутов), то внезапное изменение обнаружения, похоже, не работает. Отображаемое значение чередуется только примерно каждые 5-6 секунд, кажется довольно случайным, хотя в консоли я все еще вижу ожидаемые значения.
Когда я меняю конструктор компонента на это:
constructor(private zone: NgZone) {
this.interval = setInterval(() => {
zone.run(() => {
this.status = !this.status;
console.log('status: ' + this.status);
});
}, 2000);
}
Он снова работает снова.
Очевидно, это не выполнимое решение, так как поведение, которое я вижу в реальном приложении, намного сложнее (мне нужно было бы добавить zone.run
в десятки мест, возможно, это было бы не ремонтопригодным).
Я отлаживал это часами и не понимаю, что происходит. В профилировщике JavaScript JavaScript я в основном вижу, что страница простаивает почти все время в те 5-6 секунд, где ничего не происходит.
Это не скриншот из этого демонстрационного компонента (но он в основном выглядит одинаково), но из профилирования вкладки-компонента, который я изначально тестировал (переключение табуляции заняло столько же времени, что между видимыми действиями не было).
обновление:
После немного большего количества экспериментов то, что я нахожу довольно удивительным, также заключается в том, что вместо того, чтобы поместить код изменения статуса в вызов zone.run
, я добавляю вызов ApplicationRef.tick()
(как упоминается здесь, например: qaru.site/info/28948/...), он также НЕ работает вообще.
Я не понимаю, почему принудительное обнаружение изменений приложения ничего не делает, но вызов зоны работает как-то.
Пример кода с тиковым вызовом, который не работает:
constructor(private applicationRef:ApplicationRef) {
this.interval = setInterval(() => {
this.status = !this.status;
console.log('status: ' + this.status);
applicationRef.tick();
}, 2000);
}
В версии Angular есть ошибка. Обнаружение изменений не работает должным образом в ng-обновленных приложениях.
Подробнее см. https://github.com/angular/angular/issues/12318.
Если вы обновляете до 2.4.4, это должно решить проблему.