【问题标题】:Change detection not firing更改检测未触发
【发布时间】:2021-09-02 06:14:36
【问题描述】:

我的 Angular 11 更改检测仅在我向下滚动以进行初始页面加载时触发。如果我在订阅中调试,我的 observable 会正确发出。有什么想法吗?

我的组件:

public extras$: Observable<Order[]>;
  constructor(private userService: userService) {

  }
  async ngOnInit() {
    await this.load();
  }

  private async load() {
    this.userService.user$.subscribe(async user=> {
      if (user) {
        this.extras$ = of(await this.userService.getExtras(22456));
      }
    });
  }

我的 html 组件:

<div class="u-extras">
  <div class="main-heading"><span>User Extras</span></div>
  <ng-container *ngIf="extras$ | async as extras;else loader">
    <user-extra*ngFor="let extraof extras" [extra]=extra></user-extra>
  </ng-container>
</div>

<ng-template #loader>
  <loader-dots></loader-dots>
</ng-template>

【问题讨论】:

  • 标题完全是误会。 Change Detection 在输入/输出发生变化时由角度自动触发。您可以通过在组件的decorator 中更改它来决定哪些组件自动更新,哪些不更新。另外,为什么异步 ngOnInit 不是一个好习惯的原因:stackoverflow.com/questions/56092083/…
  • 您能否添加向我们展示您获得user$ 的组件的decorator

标签: angular angular11


【解决方案1】:

这不是创建和使用Observable 的正确方法。您也不需要使用async。服务中也没有ngOnInit

我也更喜欢将Subject 声明为私有变量并公开一个公共Observable。这使我可以控制谁可以发出值。需要注意的是,我在这里使用的是BehaviorSubject,而不是普通的Subject。由于您的服务将在组件初始化之前设置,因此我们需要确保新订阅者(在本例中为您的组件)将能够获得该值。常规主题不会向新订阅者发出值,而 BehaviorSubject 会。

//User a behavior subject, which will emit values to new subscribers
private _extras = new BehaviorSubject<Order[]>([]);
private userSub: Subscription;

constructor(private userService: userService) {
    load();
}

get extras$(): Observable<Order[]>{
    return this._extras.asObservable();
}

//Services do not have ngOnInit(), but they do have ngOnDestroy
//ngOnInit(){
//    load();
//}

ngOnDestroy(){
    //be sure to clean up any subscriptions
    this.userSub.unsubscribe();
}

private load(){
    //listen for the next user to be emitted
    this.userSub = this.userService.user$.subscribe(user => {
        //when a new user is emitted, go get some extra data
        this.userService.getExtras(22456).subscribe(extras => {
            //emit the extra data
            this.extras$.next(extras);
        })
    })
}

Here is a stackblitz 演示

【讨论】:

  • 同样的事情会发生,如果我手动调用更改检测它会出现,但显然这并不理想
  • 你是对的!我的原始示例没有进行更改检测。原因是 Subject 不会将其价值传递给新订阅者。我已经编辑了我的答案并提供了一个有效的堆栈闪电战。
猜你喜欢
  • 2021-04-09
  • 2023-04-09
  • 1970-01-01
  • 2016-04-20
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 2016-07-20
相关资源
最近更新 更多