Angular OnPush:更新的输入字符串不会更新模板
Angular OnPush: an updated Input string won't update the template
有一个默认 changeDetection
的父组件和两个 onPush
更改检测策略的子组件。在更新输入变量时,模板不会更新。我不能在 ChildBComponent
中使用异步管道,因为它是项目的全局 UI 组件,重构不是一个选项。我该怎么做?
parent.ts
@Component({
selector: 'parent',
template: `
<div>
<child-a>
<child-b [label]="firstLabel"></child-b>
<child-b [label]="secondLabel"></child-b>
<child-b label="Just a plain label"></child-b>
</child-a>
</div>`
})
export class ParentComponent implements OnInit {
public ngOnInit(): void {
this.httpService.loadData()
.subscribe(data => {
this.someValue = 1;
this.otherValue = 2;
});
}
// getters to explicitly trigger change detection
public get firstLabel(): string {
return `Something ${ this.someValue || '?'}`;
}
public get secondLabel(): string {
return `Different ${ this.otherValue || '?'}`;
}
}
子-a.ts
@Component({
selector: 'child-a',
template: `
<div>Layout wrapper</div>
<ng-content></ng-content>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildBComponent implements AfterContentInit {
}
子-b.ts
@Component({
selector: 'child-b',
template: '<div>{{ label }}</div>',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildBComponent implements AfterViewInit, OnDestroy {
@Input public label: string;
}
我尝试将 @Input
转换为 getter/setter - 但无济于事。调试时,更改正在通过,但只有在我单击组件本身时模板才会更新。投入 markForCheck()
也无济于事。
想法很有帮助。
编辑:添加 StackBlitz。请使用广泛的预览来查看问题;奇迹般地,当显示移动视图元素时它可以正常工作。
问题不在于变更检测,标签值正确反映在 html 中。 countA
和 countB
值的变化确实反映在 HTML 中,只是 CSS 给人的印象好像 html 没有更新。
在 fieldtabs.component.html
中,您有通过 <ul>
显示标签的逻辑,并且您还有 <ng-content>
.
问题是当设备的最大宽度为 767.98px
时,<ul *ngIf="!vertical" class="fieldtabs--tabs-container">
元素不会显示为以下 CSS:
@media (max-width: 767.98px) {
.fieldtabs--tabs-container {
display:none
}
}
而 <fieldtab>
即内容子项仅在设备最大宽度为 767.98px
时可见。下面是负责相同的CSS:
.fieldtabs-l {
display: none
}
@media (max-width: 767.98px) {
.fieldtabs-l {
display:flex;
align-items: center
}
}
负责显示label
的fieldtab模板html有上面的class:
<div *ngIf="!invisible" class="fieldtabs-l fieldtab--accord"
因此当设备最大宽度为 767.98px 时:
- 您的 OnPush 内容子
fieldtab
模板中存在的 {{ label }}
插值可见
- 您的 OnPush
fieldtabs
模板中存在的 {{ tab.label }}
插值不可见
当宽度大于 767.98px 时,会发生相反的情况,即 {{ tab.label}}
是您在屏幕上看到的内容,它不会更新,因为 tabs
是在 [=29] 中构建的=] 并且当 countA
和 countB
被分配新值时不会再次调用该方法。
有一个默认 changeDetection
的父组件和两个 onPush
更改检测策略的子组件。在更新输入变量时,模板不会更新。我不能在 ChildBComponent
中使用异步管道,因为它是项目的全局 UI 组件,重构不是一个选项。我该怎么做?
parent.ts
@Component({
selector: 'parent',
template: `
<div>
<child-a>
<child-b [label]="firstLabel"></child-b>
<child-b [label]="secondLabel"></child-b>
<child-b label="Just a plain label"></child-b>
</child-a>
</div>`
})
export class ParentComponent implements OnInit {
public ngOnInit(): void {
this.httpService.loadData()
.subscribe(data => {
this.someValue = 1;
this.otherValue = 2;
});
}
// getters to explicitly trigger change detection
public get firstLabel(): string {
return `Something ${ this.someValue || '?'}`;
}
public get secondLabel(): string {
return `Different ${ this.otherValue || '?'}`;
}
}
子-a.ts
@Component({
selector: 'child-a',
template: `
<div>Layout wrapper</div>
<ng-content></ng-content>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildBComponent implements AfterContentInit {
}
子-b.ts
@Component({
selector: 'child-b',
template: '<div>{{ label }}</div>',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildBComponent implements AfterViewInit, OnDestroy {
@Input public label: string;
}
我尝试将 @Input
转换为 getter/setter - 但无济于事。调试时,更改正在通过,但只有在我单击组件本身时模板才会更新。投入 markForCheck()
也无济于事。
想法很有帮助。
编辑:添加 StackBlitz。请使用广泛的预览来查看问题;奇迹般地,当显示移动视图元素时它可以正常工作。
问题不在于变更检测,标签值正确反映在 html 中。 countA
和 countB
值的变化确实反映在 HTML 中,只是 CSS 给人的印象好像 html 没有更新。
在 fieldtabs.component.html
中,您有通过 <ul>
显示标签的逻辑,并且您还有 <ng-content>
.
问题是当设备的最大宽度为 767.98px
时,<ul *ngIf="!vertical" class="fieldtabs--tabs-container">
元素不会显示为以下 CSS:
@media (max-width: 767.98px) {
.fieldtabs--tabs-container {
display:none
}
}
而 <fieldtab>
即内容子项仅在设备最大宽度为 767.98px
时可见。下面是负责相同的CSS:
.fieldtabs-l {
display: none
}
@media (max-width: 767.98px) {
.fieldtabs-l {
display:flex;
align-items: center
}
}
负责显示label
的fieldtab模板html有上面的class:
<div *ngIf="!invisible" class="fieldtabs-l fieldtab--accord"
因此当设备最大宽度为 767.98px 时:
- 您的 OnPush 内容子
fieldtab
模板中存在的{{ label }}
插值可见 - 您的 OnPush
fieldtabs
模板中存在的{{ tab.label }}
插值不可见
当宽度大于 767.98px 时,会发生相反的情况,即 {{ tab.label}}
是您在屏幕上看到的内容,它不会更新,因为 tabs
是在 [=29] 中构建的=] 并且当 countA
和 countB
被分配新值时不会再次调用该方法。