gpt4 book ai didi

javascript - Angular onPush 不会更新来自父级的子属性

转载 作者:太空狗 更新时间:2023-10-29 18:18:52 26 4
gpt4 key购买 nike

我有一个看起来像这样的子组件:

@Component({
selector: 'app-child',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
{{text}}
`
})
export class ChildComponent {
@Input() text = '';

constructor(public host: ElementRef) { }
}

还有一个看起来像这样的父组件:

@Component({
selector: 'app-parent',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<ng-content></ng-content>`
})
export class ParentComponent {
@ContentChild(ChildComponent) child: ChildComponent;

constructor(private cdr: ChangeDetectorRef) { }

ngAfterContentInit() {
this.child.text = 'hello';
this.child.host.nativeElement.addEventListener('click', () => {
this.child.text = 'from click';
this.cdr.detectChanges();
});
}

第一次分配给 text 属性时工作正常,但是当我单击按钮并尝试再次更改 text 属性时,没有任何反应。

这令人困惑,因为据我所知:1.点击事件应该触发变化检测,文本属性不同所以应该更新。2. 我明确地调用了 detectChanges(),这也应该检查我所知道的 child 。

我错过了什么?

最佳答案

该问题与 GitHub 上报告的 this issue 有关。它发生在:

  • 子组件使用OnPush变化检测策略
  • 子组件的输入属性直接在父组件代码中更改,而不是在父组件模板中进行数据绑定(bind)

AngularInDepth.com给出的解释:

The compiler doesn't have a way to generate necessary information for checking the bindings since it can't find these bindings in the template. OnPush is tightly bound to the input bindings. What's important is that Angular checks the second part of the binding (prop in the example below), not the first (i):

<child [i]="prop">

to determine whether the change detection should be run for the child component. And it does so when checking parent component. If you don't show the compiler what parent property should be used to update child input binding, it can't generate necessary information used when checking the parent. So inspecting @Input on child components isn't enough. That's the mechanism of change detection and I don't see any way it could be changed.

yurzui 在讨论中建议的一种解决方法是在设置 text 属性后在子组件中调用 ChangeDetectorRef.markForCheck,如 this stackblitz 所示。事实上,它无需在父组件中调用 ChangeDetectorRef.detectChanges 即可工作。

export class ChildComponent {

private _text = '';

@Input()
get text() {
return this._text;
}
set text(val) {
if (this._text !== val) {
this.cdRef.markForCheck();
}
this._text = val;
}

constructor(public host: ElementRef, private cdRef: ChangeDetectorRef) { }
}

关于javascript - Angular onPush 不会更新来自父级的子属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49865267/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com