Обнаружение изменений Angular2 в методах привязки жизненного цикла

#angular

#angular

Вопрос:

Я хочу показать счетчик в ngOnInit() и скрыть его в ngAfterViewInit(). Но это не работает:

  • без setTimeout() ничего не происходит
  • с помощью setTimeout() счетчик показывает и скрывает (мигает), но после ngAfterViewInit()

http://plnkr.co/edit/M1g7DT1Eks2gtuSXi1B1?p=preview

В этом примере компонент spinner (spinner.ts) представляет собой тег div, который изменяет цвет фона.

 import {Component, Input} from '@angular/core'

@Component({
  selector: 'my-spinner',
  template: `
    <div [style.background-color]="status ? 'red' : 'yellow'" >
      spinner is {{status}}
    </div>
  `,
})
export class MySpinner {
  @Input() status: boolean;

  status:boolean;
  constructor() {
    this.status = false;
  }

  getColor() {
    if (status) {
      return "red";
    } else {
      return "yellow";
    }
  }

  ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
        for (let propName in changes) {
            let chng = changes[propName];
            let cur  = JSON.stringify(chng.currentValue);
            let prev = JSON.stringify(chng.previousValue);
            console.trace(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
        }
    }
}
  

При нажатии на «ссылку на мой компонент» (mycomponent.ts) я хочу, чтобы счетчик цвета фона был красным между ngOnInit() и ngAfterViewInit().

 import {Component, Input, ApplicationRef} from '@angular/core';
import {AppService} from './appservice';

@Component({
  selector: 'my-component',
  template: `
    <div>
      This is my component!
    </div>
  `,
})
export class MyComponent {

  constructor(private appSvc: AppService) {

  }

  ngOnInit(): void {

    this.appSvc.setVisible(true);
    console.log('MyComponent - ngOnInit');
  }

  ngAfterViewInit() {
    var start = new Date().getTime();
        for (var i = 0; i < 1e7; i  ) {
            if ((new Date().getTime() - start) > 10000){
                break;
            }
        }

    //setTimeout(() => { this.appSvc.setVisible(false)});
    this.appSvc.setVisible(false);

    console.log('MyComponent - ngAfterViewInit');
  }

}
  

Каково решение?


Обновить

Я обновляю образец http://plnkr.co/edit/M1g7DT1Eks2gtuSXi1B1?p=preview чтобы использовать observable.

Я установил счетчик для отображения в ngOnInit(), но ngOnChanges() компонента счетчика вызывается после ngAfterViewInit()

Консоль журнала :

 VM437 AppService - setVisible - true  
VM439 mycomponent.ts!transpiled:33 MyComponent - ngOnInit  
VM439 mycomponent.ts!transpiled:37 MyComponent - ngAfterViewInit -begin  
VM439 mycomponent.ts!transpiled:47 MyComponent - ngAfterViewInit -end  
**VM440 spinner.ts!transpiled:38 status: currentValue = true, previousValue = fals**  
VM437 appservice.ts!transpiled:27 AppService - setVisible - false  
VM439 mycomponent.ts!transpiled:45 Observable Complete  
**VM440 spinner.ts!transpiled:38 status: currentValue = false, previousValue = true**
  

Итак, кажется, что в методах привязки жизненного цикла нет немедленного обнаружения изменений? Правильно или неправильно?

Комментарии:

1. Объясните мне, какова может быть цель отображения и скрытия элемента в этих двух перехватах жизненного цикла?

2. В основном это делается для того, чтобы как можно скорее показать счетчик (в ngOnInit ()), но он отображается только после ngAfterViewInit (), поэтому в моем вопросе я обновляю свой вопрос и изменяю пример, чтобы использовать наблюдаемый

Ответ №1:

Для достижения этого, я думаю, лучше поместить счетчик непосредственно в качестве неуглового компонента внутри <my-app> тегов. Таким образом, вы можете получить счетчик, который отображается до полной загрузки приложения.

Если вы попытаетесь добиться этого с помощью компонентов angular, счетчик не будет отображаться до тех пор, пока не будет загружено приложение angular, а когда оно загружено, счетчик в этот момент бесполезен.