Пользовательский интерфейс Angular 6 не обновлен

У меня есть 3 компонента:

c1 содержит c2 и c3

c2 содержит флажок. Когда флажок установлен, я запускаю событие в выходную переменную.

<input type="checkbox" [checked]="displayAxialMap" (click)="onToggleAxialMap()" />

и в компоненте:

onToggleAxialMap() {
    this.displayAxialMap = !this.displayAxialMap;
    this.toggleMap.emit(<Map>{ display: this.displayAxialMap, mapType: MapType.AXIALMAP, loading: true });
}

в c1 у меня есть объект поведения, называемый displayMap

<c2 (toggleMap)="displayMap.next($event)"></c2>

в c1 я также передаю значение displayMap в c3

<c3 [displayMap]="displayMap"></c3>

c3 в ngOnInit() я делаю так:

this.displayMap.subscribe(map => {
   this.loading = map.loading;
   this.drawAxialMapCanvas();
   this.loading = false;
}) 

this.loading инициализируется значением false.

Все работает (поэтому нет проблем с передачей данных через компоненты). Но this.drawAxialMapCanvas(); это функция, выполнение которой занимает много времени (3-4 секунды), и я вижу два странных поведения:

  1. флажок в c2 меняется на отмеченный только после завершения this.drawAxialMapCanvas().
  2. локальная переменная «загрузка» внутри c3 (если я отлаживаю код) правильно переходит от false к true и снова к false. Но если я помещу эту переменную в шаблон:

‹... *ngIf"loading">Загрузка...

Он никогда не появляется... Он принимает только последнее значение!

Кажется, что мой пользовательский интерфейс обновляется только после завершения this.drawAxialMapCanvas(). Что я делаю неправильно?


person G10    schedule 19.09.2018    source источник
comment
можете ли вы создать stackbliz, пожалуйста   -  person devpato    schedule 19.09.2018


Ответы (1)


Для 1) это нормально, javascript - это один поток, поэтому все просто блокируется this.drawAxialMapCanvas

2) Вы пытаетесь показать сообщение о загрузке, но у вас здесь та же проблема, angular не обновляется, так как the.drawAxialMap не завершен и блокирует поток (4 секунды действительно долго для неасинхронной загрузки).

Вы можете сначала запустить this.drawAxialMap в следующем цикле событий, выполнив:

this.displayMap.subscribe(map => {
   this.loading = map.loading;
   setTimeout( () => {
    this.drawAxialMapCanvas();
    this.loading = false;
   )};
});

Это позволит обновить время (флажок, сообщение..)

В любом случае вы должны что-то сделать с this.drawAxialMapCanvas(); Я никогда не сталкивался с этой ситуацией, но, возможно, использовал работника или загрузку по частям, используя что-то вроде [setTimeout() / setImmediate()], чтобы дать пользовательскому интерфейсу время для управления пользовательским событием и т. д.

person xrobert35    schedule 19.09.2018