Angular OnPush不更新模板

时间:2019-09-24 04:26:45

标签: angular angular-changedetection

我有两个组件,这两个组件都设置为OnPush。调用accountLoading后,父组件将getAccount()设置为true,一旦调用完成,则将accountLoading设置为false。如预期的那样,控制台输出:

  

this.accountLoading为真

其次:

  

this.accountLoading为假

但是模板没有更新,并且一直认为accountLoading是正确的。值更改时如何使模板按预期更新?我想将更改检测保留为OnPush。

父组件:

TypeScript:

public accountLoading: boolean;
...

getAccount() {
  this.accountLoading = true;
    this.authStore
        .pipe(select(fromAuthStore.getAccountData))
        .subscribe(account => {
          if (account) {
            this.accountLoading = false;
          }
          console.log('this.accountLoading', this.accountLoading);
        });

  // Loading account if it hasn't yet been loaded
  this.authService.getAccount();
}

HTML:

<child-component
  [accountLoading]="accountLoading">
</child-component>

子组件

TypeScript:

@Input() accountLoading: boolean;
...

HTML:

<p *ngIf="accountLoading">
  Loading...
</p>

3 个答案:

答案 0 :(得分:3)

尝试行为主题

public accountLoading$: BehaviorSubject<boolean>(false);
...

getAccount() {
  this.accountLoading$.next(true);
    this.authStore
        .pipe(select(fromAuthStore.getAccountData))
        .subscribe(account => {
          if (account) {
            this.accountLoading$.next(false);
          }
        });

  // Loading account if it hasn't yet been loaded
  this.authService.getAccount();
}

并在模板中使用异步管道

<p *ngIf="accountLoading$ | async">
  Loading...
</p>

我已经编写了一个库来为您https://github.com/adriandavidbrand/ngx-rxcache处理很多此类状态管理。在这里https://medium.com/@adrianbrand/angular-state-management-with-rxcache-468a865fc3fb

进行阅读

答案 1 :(得分:0)

如果您的两个组件都使用OnPush更改检测策略,则父模板不会更新子模板。您的子组件将需要实现OnChanges生命周期挂钩,并且当输入值更改时,您可以在那里触发更改检测。

答案 2 :(得分:0)

我会用标准的可观察模式来做到这一点:

public accountLoading$: Observable<boolean>;

...

getAccount() {
   this.accountLoading$ = this.authStore
        .pipe(select(fromAuthStore.getAccountData), map(account => !!account));


  // Loading account if it hasn't yet been loaded
  this.authService.getAccount();
}

HTML:

<child-component
  [accountLoading]="accountLoading$ | async">
</child-component>