2
  • 角 6.0.1
  • ngRx 6.0.1

我在视图中设置了一个插值:

{{firstName}}

当它绑定的字段的值发生变化时,它不会更新。但是,该值正在发生变化-如果我将其注销到订阅内的控制台,我会看到更新后的值。它只是不会在 UI 中更新。

以下是相关代码:

从我的组件订阅:

private subscribeToCurrentPerson(): void {
    this.tState$ = this.store
      .pipe(select(selectors.getCurrentPerson), takeWhile(() => this.componentActive))
      .subscribe((cp: Person) => {
        if (cp) {
          const name: string = cp.primaryName.value.parsedValue.givenNames[0];
          this.firstName = name;
          console.log('name: ' + name);  // <-- this shows correct new value
        }
  });
}

subscribeToCurrentPerson从组件的 ngOnInit 调用。在此之前,该firstName属性是未定义的。

选择selectors.getCurrentPerson器如下所示:

export const getCurrentPerson: MemoizedSelector<{}, Person> = 
    createSelector(getTState, (tState: ITState) => {
      console.log('selector: ', tState); // <-- this logs the correct new value
      return tState ? tState.currentPerson : null;
    });  

从选择器返回的currentPerson值是一个新创建的对象。这是在应用程序的第一次运行时发生的,因此在此之前tState是未定义的。

如果我注入ChangeDetectorRef我的构造函数并cdr.detectChanges()在订阅中调用,UI 会更新。但在我看来,我通常不需要ChangeDetectorRef像这样使用它,它应该“正常工作”。

我认为问题在于我的深层嵌套属性(cp.primaryName.value.parsedValue.givenNames)。我从一个非 ngRx 项目继承了这些实体,但我认为下一步是尝试扁平化该结构,看看这是否会使 ngRx 和 Angular 变化检测器更快乐。

还有什么我想念的吗?

更新

通过简单地更新订阅内我的组件上的本地属性,我已经将深层嵌套的属性排除在外。所以subscribeToCurrentPerson函数现在看起来像这样:

private subscribeToCurrentPerson(): void {
        this.tState$ = this.store
          .pipe(select(selectors.getCurrentPerson), takeWhile(() => this.componentActive))
          .subscribe((cp: Person) => {
            this.myProp = 'goodbye';
            this['newProp'] = 'world';
      });
    }

myProp是我为测试添加的组件上的现有属性。 newProp直到通过订阅内的括号表示法添加它才存在。结果如下:

  • myProp未更新 - 它显示了我在声明时分配的值。但是,如果我在声明属性时未分配值,则订阅中分配的值会正确显示在 UI 中。
  • newProp 在 UI 中正确显示

我现在完全困惑了。 似乎一旦属性具有值,它就永远不会在 UI 中更新,即使值本身确实发生了变化(我可以通过在更新值后登录到控制台来判断)。

我没有ChangeDetectionStrategy为组件明确设置 ,所以它是Default.

如果我打电话detectChanges,一切正常,但我认为这没有必要。

4

2 回答 2

5

当父组件将其更改检测策略设置为时OnPush,Angular 的更改检测机制将不会检查此父组件的树,尽管ngOnChanges每次任何@Input属性更改时仍会调用此父组件及其子组件的方法。要让 Angular 知道此树中的某些组件需要更新,请将 aChangeDetectorRef注入该组件并使用其 API 通知 Angular 更新,例如detectChangesmarkForCheck

于 2018-08-05T18:17:09.720 回答
1

很多时候来自组件的数据更新不会反映 HTML 模板。在这种情况下,您可以将插值与三元运算符一起使用。

{{firstName ? firstName : ''}}
于 2019-03-07T12:42:17.243 回答