我正在开发一个大型应用程序,并且在检测更改时遇到了一些问题。
父组件ts:
使用changeDetection: ChangeDetectionStrategy.OnPush
我有一个可以观察到的变量
loaderOverlay$: Observable<boolean>;
this.loaderOverlay$ = this.store.pipe(
select(selectors.loaderOverlaySelector)
);此变量从子组件的rxjs操作中更新。然后经过rxjs过程。(动作->减速器->选择器)
父组件
<div *ngif="(loaderOverlay$ | async)"></div>
子组件#1 (其中im分派我的操作):
myFunction() {
this.store.dispatch(new actions.LoaderOverlay(true));
}我的问题是,一旦我派遣行动,*ngif是非常不稳定的。它似乎没有按我所希望的方式工作(分派操作,将值更改为true,这样div就会出现)。这很奇怪,因为如果我在还原器中使用console.log(action.payload),那么这个值实际上正在被更新,但是*ngif不起作用。更奇怪的是,当我悬停在其他组件上时,它似乎就开始了。
我认为我已经将其缩小到更改检测范围,因为在父组件中,如果我这样做了:
ngAfterViewChecked(){
this.changeDetector.detectChanges();
}好像对我有用。我的问题是,ngAfterViewChecked似乎被触发了大量的时间,我害怕性能问题。
这里可能发生了什么,我能做些什么来解决这个奇怪的问题?
发布于 2019-02-04 09:42:50
您的loaderOverlay$发出的值是否计算为true?我在stackblitz上创建了类似的代码(正如您所描述的),我似乎无法重现您遇到的bug。它要么是一个修复了角/ngrx的bug,要么是您发出的值没有计算为true ( select不是很好,并且返回未定义的或其他什么的)。试着挖掘可观察到的结果并记录结果。
https://stackblitz.com/edit/angular-ngrx-update?file=src/app/app.component.css
稍后编辑:
正如Cristian在评论中指出的那样,markForCheck (从异步管道内部)在从外部角度调用它时不会触发更改检测。作为修复,您可以在管道中使用区域调度程序,或者检测更改来自何处,并修补该区域以触发角内的更改检测(因为应用程序的其他区域可能会出现问题)。
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()),
);发布于 2019-01-29 20:58:29
从您的示例来看,onPush策略似乎没有得到正确的使用。onPush策略意味着,即使组件中的变量正在更新,如果组件的@inputs没有改变,组件也不一定会更新。根据我在您的示例中可以收集到的信息,父组件的@input引用没有发生变化,这意味着更改检测并不像您预期的那样发生。
为了解决这个问题,我建议更新父组件(它订阅存储更新),或者使用defaultStrategy或者根据需要手动调用markForCheck()来触发更新。
发布于 2019-02-04 09:16:58
我也有过类似的问题。通过编辑输入字段,结果将从后端获取并显示在列表中。除非我在其他地方徘徊或单击,否则列表不会更新。
我通过从后端获取数据之后添加一个手动更改检测来修正它。
constructor(private cd: ChangeDetectorRef) {}
fetchData.subscribe(results => {
AddResultsToStore(results);
this.cd.detectChanges();
});https://stackoverflow.com/questions/54386088
复制相似问题