Angular LifecyleHooks和@ViewChild什么时候有效?

时间:2017-09-29 18:37:59

标签: angular lifecycle

我有点困惑。我以为我基本上理解了角度组件的生命周期,但是我遇到了一个有趣的案例,其中组件的@Input未定义。

在这种情况下,我有两个应用程序实例。当注销处于挂起状态时,将显示给定组件: LogoutWarning ,然后用户可以刷新登录令牌并继续。这很好。

当第一个应用程序更新登录令牌并且隐藏显示 LogoutWarning 组件时,实例会出现。在第一个申请中一切都很好。

第二个应用程序还显示 LogoutWarning 组件,因为它检测到登录令牌将过期并显示 LogoutWarning模式,然后它会注意到登录令牌已更新并调用LogoutWarning.cancel()来隐藏模态。在这种情况下,this.logoutWarningModal.hide()会爆炸,因为this.logoutWarningModal是 UNDEFINED ,即使lifecyle ngAfterViewInit()显示已定义this.logoutWarningModal。

我对此非常惊讶。如果我只是检查this.logoutWarningModal是否未定义,而不是调用this.logoutWarningModal.hide(),则所有工作都按预期工作。但是为什么this.logoutWarningModal在这里未定义???

LoutWarning 组件的代码很简单:

@Component({
  selector: 'logoutWarning',
  template: `
    <div bsModal #logoutWarning="bs-modal" [config]="{ show: true }" class="modal fade" tabindex="-1" role="dialog"
     aria-labelledby="new application version avaliable" aria-hidden="true" (onHidden)="hidden()">
      <div class="modal-dialog modal-sm">
        <div class="modal-content">
          <div class="modal-header">
            <div class="app_header">
              <div class="app_icon"><img src="assets/images/tracker_hi_res_512.gif"></div>
              <div class="app_name">Tracker</div>
            </div>
          </div>
          <div class="modal-body center-message">
            <span class="bold">You will be logged out in </span>
            <span><strong>{{minutes | async}}</strong> minutes!</span>
          </div>
          <div class="modal-footer">
            <button class="btn btn-primary" (click)="ok()">Stay Logged In</button>
          </div>
        </div>
      </div>
</div>
`
})
export class LogoutWarning implements OnInit {
  @ViewChild('logoutWarning') public logoutWarningModal: ModalDirective;
  @Input() minutes: string;

  constructor(private userCondition: UserCondition, private broadcaster: BroadCaster, private versionS: Version, private auth: AuthService) {
  }

  public ok(): void {
    this.auth.renewLogin(this.userCondition, this.userCondition.minutesDurationUntilLogout.getValue());
    this.logoutWarningModal.hide();
   }

  public cancel() {
    if (this.userCondition.bShowLogoutWarning) {
        this.logoutWarningModal.hide();
    }
  }

  public hidden() {
    // reset the state of the dialog so that it can be reshown.
    this.userCondition.bShowLogoutWarning = false;
    this.logoutWarningModal.show();
  }


  public ngOnInit() {
    console.log('ngOnInit()');
    console.log('this:', this, this.logoutWarningModal);
  }

}

当userCondtion.bShowLogoutWarning为true并在我的主应用程序中显示时显示该组件。 html的相关部分是:

<logoutWarning *ngIf="userCondition.bShowLogoutWarning" [minutes]="userCondition.minutesUntilLogout"></logoutWarning>

两个应用程序都记录:

 ngOnInit()    logoutWarning.component.ts?f8b4:55 
 this: LogoutWarning {userCondition: UserCondition, broadcaster: BroadCaster, versionS: Version, auth: AuthService, logoutWarningModal: ModalDirective, …} 
 ModalDirective {onShow: EventEmitter, onShown: EventEmitter, onHide: EventEmitter, onHidden: EventEmitter, isAnimated: true, …} 
    userCondition.service.ts?0111:164 

然后在第一个应用程序更新登录令牌后,第二个应用程序显示:

 this: LogoutWarning {userCondition: UserCondition, broadcaster: BroadCaster, versionS: Version, auth: AuthService} undefined

其中this.logoutWarningModal是UNDEFINED!

感谢您的见解!

1 个答案:

答案 0 :(得分:2)

@ViewChild将返回undefined直到它被初始化,并且在OnInit()中就是这种情况。请在AfterViewInit()中检查它:

ngAfterViewInit() {
   console.log('ngAfterViewInit()');
   console.log('this:', this, this.logoutWarningModal);
    // this will returns the object
}