Angular 内插值未在订阅时更新
Angular interpolated value not updating on subscription
- Angular6.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
,一切正常,但我认为没有必要。
当父组件的变更检测策略设置为 OnPush
时,angular 的变更检测机制将不会检查该父组件的组件树,尽管该父组件及其子组件的 ngOnChanges
方法仍然在每次任何 @Input
属性更改时被调用。要让 angular 知道此树中的某些组件需要更新,请将 ChangeDetectorRef
注入该组件并使用其 API 通知 angular 有关更新,例如 detectChanges
或 markForCheck
很多时候来自组件的数据更新不会反映 HTML 模板。在这种情况下,您可以使用三元运算符进行插值。
{{firstName ? firstName : ''}}
- Angular6.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
,一切正常,但我认为没有必要。
当父组件的变更检测策略设置为 OnPush
时,angular 的变更检测机制将不会检查该父组件的组件树,尽管该父组件及其子组件的 ngOnChanges
方法仍然在每次任何 @Input
属性更改时被调用。要让 angular 知道此树中的某些组件需要更新,请将 ChangeDetectorRef
注入该组件并使用其 API 通知 angular 有关更新,例如 detectChanges
或 markForCheck
很多时候来自组件的数据更新不会反映 HTML 模板。在这种情况下,您可以使用三元运算符进行插值。
{{firstName ? firstName : ''}}