使用Angular 4.3和以下的Plunkr.
请考虑以下组件:
@Component({
selector: 'my-app',
template: `
<div>
<button type="button" (click)="toggle()">Toggle</button>
<div #anchor></div>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class App {
@ViewChild('anchor', {read: ViewContainerRef}) anchor: ViewContainerRef;
dynamicRef: ComponentRef;
value = true;
constructor(private cfr: ComponentFactoryResolver, private cdr: ChangeDetectorRef) {}
ngAfterViewInit(): void {
let factory = this.cfr.resolveComponentFactory(Dynamic);
this.dynamicRef = this.anchor.createComponent(factory);
this.dynamicRef.instance.value = this.value;
this.dynamicRef.changeDetectorRef.detectChanges();
}
toggle(): void {
this.value = !this.value;
this.dynamicRef.instance.value = this.value;
this.dynamicRef.changeDetectorRef.detectChanges();
}
}
@Component({
template: `Value: {{value}}`,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class Dynamic {
@Input() value = true;
}
Run Code Online (Sandbox Code Playgroud)
该App组件Dynamic使用标准ComponentFactoryResolver+ ViewContainerRef策略创建组件.两个组件都有OnPush变更检测策略.App.toggle()调用该方法时,它会切换App.value,传播此新值Dynamic.value并强制在动态组件的更改检测器上运行更改检测.我希望动态组件的模板能够显示正确的值,但实际上它永远不会改变.将两个组件切换到Default更改检测策略可提供预期的行为.
为什么动态组件模板不能正确重新渲染,如何修复?
每个动态创建的组件都有一个主机视图.所以你有以下层次结构:
AppComponentView
DynamicComponentHostView
DynamicComponentView
Run Code Online (Sandbox Code Playgroud)
当你这样做时:
this.dynamicRef.changeDetectorRef
Run Code Online (Sandbox Code Playgroud)
你得到changeDetectorRef了DynamicComponentHostView.当你运行时,detectChanges你运行变更检测DynamicComponentHostView,而不是DynamicComponentView.
然后,如果设置OnPush策略,则父组件将更新子组件的绑定,并决定是否对子组件运行更改检测.但是,重要的是,在模板编译期间定义输入绑定.动态组件不是这种情况.因此,如果要使用OnPush,则必须在此组件上手动触发更改检测.要做到这一点,你需要获得变化检测器DynamicComponentView.你可以这样做:
export class Dynamic {
@Input() value = true;
constructor(public cd: ChangeDetectorRef) {
}
Run Code Online (Sandbox Code Playgroud)
然后触发更改检测,如下所示:
this.dynamicRef.instance.cd.detectChanges();
Run Code Online (Sandbox Code Playgroud)
有关更改检测的更多信息,请阅读有关Angular中的更改检测的所有信息.
| 归档时间: |
|
| 查看次数: |
963 次 |
| 最近记录: |