有这样的错误:
错误错误:ExpressionChangedAfterItHasBeenCheckedError:表达 检查后已更改。上一个值:'ngTemplateOutlet: 未定义”。当前值:“ ngTemplateOutlet:[对象对象]”。
在viewDebugError(core.js:9775)
在expressionChangedAfterItHasBeenCheckedError(core.js:9753)
在checkBindingNoChanges(core.js:9920)
在checkNoChangesNodeInline(core.js:13970)
在checkNoChangesNode(core.js:13942)
在debugCheckNoChangesNode(core.js:14771)
在debugCheckDirectivesFn(core.js:14673)
at Object.eval [作为updateDirectives](ShowEventComponent.html:73)
在Object.debugUpdateDirectives [作为updateDirectives](core.js:14655)
在checkNoChangesView(core.js:13780)
她之所以出现是因为
<tr *ngFor="let user of users">
<ng-template [ngTemplateOutlet]="loadTemplate(user)"
[ngTemplateOutletContext]="{ $implicit: user}">
</ng-template>
</tr>
我该如何解决?
我使用Angular 5.2.0,rxjs 5.5.6
答案 0 :(得分:2)
我最近解决了一个类似的问题,但找不到太多帮助,所以我将提供一些帮助。
首先,这仅在开发人员模式下发生,但这是一个严重的问题。当Angular运行变更检测时,它将跟踪其所有绑定值(例如ngTemplateOutlet),然后将其与变更检测周期结束后的值进行比较。
出现此错误的原因是因为您在html中设置了[ngTemplateOutlet]的方法。这导致该方法(loadTemplate(user))每发生一次更改检测就运行一次。这可能是该方法运行的5或10倍,这并不理想。
第一次将该值设置为undefined,然后在随后的周期中更新该值。我猜想loadTemplate返回的是TemplateRef,但是第一次运行该方法时,未定义TemplateRef,这就是原因。
有很多方法可以解决此问题,我需要查看您的component.ts代码。但是必须进行2次更改。首先,您需要不使用方法来设置[ngTemplateOutlet]。您可以使用组件Observable或组件字段。但是,第二,您还需要在适当的时间设置该字段或可观察的字段。您要延迟直到定义了模板。您可以在ngOnInit中执行此操作,方法是将设置字段的代码包装在setTimeout()中,或者如果使用Observable,则使用lettable rxjs delay(0)。
再次,我需要查看loadTemplate(user)和component.ts中的逻辑,以确切显示如何安排它。
您还可以将所需数据从父组件输入到此组件,然后将使用该数据的逻辑放在[ngTemplate]
之后答案 1 :(得分:1)
这与更改检测有关。你可以在这里读更多关于它的内容。我通过使用ChangeDetectorRef的detectChanges()方法解决了这个问题。
constructor(private cdr: ChangeDetectorRef) {}
ngOnInit() {}
ngAfterViewInit(): void {
this.cdr.detectChanges();
}
您需要实现AfterViewInit接口。
答案 2 :(得分:0)
就像Envil一样,您可以将loadTemplate()函数的内容包装到setTimeout
中,例如:
setTimeout(() => {
yourTemplateLoadingMechanism();
});
但是通常我会避免在模板中调用函数,因为它们一遍又一遍地调用,这使调试变得很困难,并且降低了性能。相反,您可以预取所有模板,并像往常一样以双向绑定的方式提供它们,甚至可以将rxjs
Observables
与async
键一起使用,这样做可以更有效地规避您的问题。>
答案 3 :(得分:0)
您应该在TemplateRef
功能上设置AfterContentInit