Angular LifecyleHooks 以及 @ViewChild 何时有效?

问题描述 投票:0回答:1

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

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

当第一个应用程序更新登录令牌时,该实例就会出现,并隐藏显示 LogoutWarning 组件。第一次应用一切顺利。

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

感谢您的见解!

javascript angular typescript lifecycle
1个回答
11
投票

@ViewChild 会返回

undefined
直到它被初始化,OnInit() 中就是这种情况。而是在 AfterViewInit() 中检查它:

ngAfterViewInit() {
   console.log('ngAfterViewInit()');
   console.log('this:', this, this.logoutWarningModal);
    // this will returns the object
}
© www.soinside.com 2019 - 2024. All rights reserved.