首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >奇数变化检测行为角2+

奇数变化检测行为角2+
EN

Stack Overflow用户
提问于 2019-01-27 07:44:37
回答 3查看 1.2K关注 0票数 10

我正在开发一个大型应用程序,并且在检测更改时遇到了一些问题。

父组件ts:

使用changeDetection: ChangeDetectionStrategy.OnPush

我有一个可以观察到的变量

loaderOverlay$: Observable<boolean>;

代码语言:javascript
复制
this.loaderOverlay$ = this.store.pipe(
  select(selectors.loaderOverlaySelector)
);

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

父组件

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

子组件#1 (其中im分派我的操作):

代码语言:javascript
复制
myFunction() {
  this.store.dispatch(new actions.LoaderOverlay(true));
}

我的问题是,一旦我派遣行动,*ngif是非常不稳定的。它似乎没有按我所希望的方式工作(分派操作,将值更改为true,这样div就会出现)。这很奇怪,因为如果我在还原器中使用console.log(action.payload),那么这个值实际上正在被更新,但是*ngif不起作用。更奇怪的是,当我悬停在其他组件上时,它似乎就开始了。

我认为我已经将其缩小到更改检测范围,因为在父组件中,如果我这样做了:

代码语言:javascript
复制
ngAfterViewChecked(){
   this.changeDetector.detectChanges();
}

好像对我有用。我的问题是,ngAfterViewChecked似乎被触发了大量的时间,我害怕性能问题。

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

EN

回答 3

Stack Overflow用户

发布于 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

代码语言:javascript
复制
public constructor(
  @Inject(ZoneScheduler)
  private readonly zoneScheduler: SchedulerLike,
) {}

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

或者你可以直接用tick appRef

代码语言:javascript
复制
public constructor(
  private appRef: ApplicationRef,
) {}

this.loaderOverlay$ = this.store.pipe(
  select(selectors.loaderOverlaySelector),
  tap(_ => this.appRef.tick()),
);
票数 5
EN

Stack Overflow用户

发布于 2019-01-29 20:58:29

从您的示例来看,onPush策略似乎没有得到正确的使用。onPush策略意味着,即使组件中的变量正在更新,如果组件的@inputs没有改变,组件也不一定会更新。根据我在您的示例中可以收集到的信息,父组件的@input引用没有发生变化,这意味着更改检测并不像您预期的那样发生。

为了解决这个问题,我建议更新父组件(它订阅存储更新),或者使用defaultStrategy或者根据需要手动调用markForCheck()来触发更新。

票数 3
EN

Stack Overflow用户

发布于 2019-02-04 09:16:58

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

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

代码语言:javascript
复制
constructor(private cd: ChangeDetectorRef) {}

fetchData.subscribe(results => {
   AddResultsToStore(results);
   this.cd.detectChanges();
});
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54386088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档