代码之家  ›  专栏  ›  技术社区  ›  cup_of

奇数变化检测行为2+

  •  9
  • cup_of  · 技术社区  · 5 年前

    使用 changeDetection: ChangeDetectionStrategy.OnPush

    我有一个可观测的变量

    loaderOverlay$: Observable<boolean>;

    this.loaderOverlay$ = this.store.pipe(
      select(selectors.loaderOverlaySelector)
    );
    

    此变量通过子组件的rxjs操作进行更新。然后进行rxjs过程(行动->减速器->选择器)

    父组件HTML

    <div *ngif="(loaderOverlay$ | async)"></div>

    Child#1组件(我在其中发送我的操作):

    myFunction() {
      this.store.dispatch(new actions.LoaderOverlay(true));
    }
    

    我的问题是,一旦我发布了行动 *ngif console.log(action.payload) 在reducer中,值实际上正在更新,但是 *ngif

    我想我已经把范围缩小到了变更检测,因为在父组件中,如果我这样做:

    ngAfterViewChecked(){
       this.changeDetector.detectChanges();
    }
    

    这似乎对我有用。我的问题是 ngAfterViewChecked

    这里可能发生了什么,我能做些什么来解决这个奇怪的问题?

    3 回复  |  直到 4 年前
        1
  •  5
  •   Andrei Tătar    5 年前

    你的 loaderOverlay$ 发射值评估为 true

    https://stackblitz.com/edit/angular-ngrx-update?file=src/app/app.component.css

    稍后编辑:

    正如克里斯蒂安·特拉纳在评论中指出的, markForCheck (从异步管道内部)从外部调用时不会触发更改检测。作为修复,您可以在管道中使用区域调度器,或者检测更改来自何处,并修补该区域以触发angular内部的更改检测(因为应用程序的其他区域可能存在问题)。

    https://www.npmjs.com/package/ngx-zone-scheduler?activeTab=readme

    public constructor(
      @Inject(ZoneScheduler)
      private readonly zoneScheduler: SchedulerLike,
    ) {}
    
    this.loaderOverlay$ = this.store.pipe(
      select(selectors.loaderOverlaySelector),
      observeOn(this.zoneScheduler),
    );
    

    或者你可以 tick 这个 appRef

    public constructor(
      private appRef: ApplicationRef,
    ) {}
    
    this.loaderOverlay$ = this.store.pipe(
      select(selectors.loaderOverlaySelector),
      tap(_ => this.appRef.tick()),
    );
    
        2
  •  3
  •   JusMalcolm    5 年前

    onPush 策略没有被正确使用。这个 策略意味着如果组件的 @inputs @input 引用没有更改,这意味着更改检测没有按预期进行。

    defaultStrategy 或手动呼叫 markForCheck() 根据需要触发更新。

        3
  •  3
  •   Edito    5 年前

    我也有类似的问题。通过编辑输入字段,结果将从后端获取并显示在列表中。除非我将鼠标悬停在其他位置或单击其他位置,否则列表不会更新。

    我通过在从后端获取数据后添加一个手动更改检测来修复它。

    constructor(private cd: ChangeDetectorRef) {}
    
    fetchData.subscribe(results => {
       AddResultsToStore(results);
       this.cd.detectChanges();
    });