首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检查后,表达式发生了更改。先前的值:'ngTemplateOutlet: undefined‘。当前值:'ngTemplateOutlet:[object Object]‘

检查后,表达式发生了更改。先前的值:'ngTemplateOutlet: undefined‘。当前值:'ngTemplateOutlet:[object Object]‘
EN

Stack Overflow用户
提问于 2018-07-04 10:05:33
回答 5查看 5.6K关注 0票数 4

有这样一个错误:

错误: ExpressionChangedAfterItHasBeenCheckedError:表达式检查后发生了更改。先前的值:'ngTemplateOutlet: undefined‘。当前值:'ngTemplateOutlet: object Object‘。 在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) 在Object.eval as updateDirectives 在Object.debugUpdateDirectives as updateDirectives 在checkNoChangesView (core.js:13780)

她出现的原因是:

代码语言:javascript
复制
<tr *ngFor="let user of users">
    <ng-template [ngTemplateOutlet]="loadTemplate(user)" 
                [ngTemplateOutletContext]="{ $implicit: user}">
    </ng-template>
</tr>

我怎么才能修好它?

我使用的是角5.2.0,rxjs 5.5.6

EN

回答 5

Stack Overflow用户

发布于 2019-09-28 13:12:56

这与变化检测有关。你可以在这里读到更多关于它的内容。我使用detectChanges()方法解决了这个问题。

代码语言:javascript
复制
constructor(private cdr: ChangeDetectorRef) {}

  ngOnInit() {}

  ngAfterViewInit(): void {
    this.cdr.detectChanges();
  }

您需要实现AfterViewInit接口。

票数 8
EN

Stack Overflow用户

发布于 2018-10-21 20:38:39

我最近解决了一个类似的问题,但我找不到多少帮助,所以我会提供一些帮助。

首先,这只发生在dev模式下,但这是一个严重的问题。当角运行变化检测时,它会跟踪所有的绑定值(如ngTemplateOutlet),然后将该值与变化检测周期结束后的值进行比较。

之所以会出现此错误,是因为在html中有一个设置ngTemplateOutlet的方法。这将导致该方法(loadTemplate(用户))运行每次发生更改检测。这可能是该方法运行的5到10倍,这并不理想。

第一次通过该值被设置为未定义,在随后的周期中,该值将被更新。我猜想loadTemplate正在返回一个TemplateRef,但是当该方法第一次运行时,TemplateRef没有定义,这就是原因。

有很多方法可以解决这个问题,我需要看到您的component.ts代码。但是有两个变化必须发生。首先,您需要不使用方法来设置ngTemplateOutlet。您可以使用可观察的组件或组件字段。但是第二,你也需要在正确的时间设定场或可观察的范围。您希望延迟到定义了模板。您可以在ngOnInit中通过将设置字段的代码包装在setTimeout()中,或者使用可访问的rxjs延迟(0)(如果使用可观测的话)来实现这一点。

同样,我需要查看loadTemplate(用户)和component.ts中的逻辑,以准确地展示如何安排它。

您还可以将所需的数据从父组件输入到此组件,然后将使用该数据的逻辑放在ngTemplate之后。

票数 5
EN

Stack Overflow用户

发布于 2018-10-21 20:54:23

就像发布的Envil一样,您可以将loadTemplate()函数的内容包装到setTimeout中,如下所示:

代码语言:javascript
复制
    setTimeout(() => {
        yourTemplateLoadingMechanism();
    });

但是一般来说,我会避免在templats中调用函数,因为它们一次又一次地被调用,这就使得调试变得困难,并且降低了性能。相反,您可以预取所有模板,并按照通常的双向绑定方式提供它们,甚至可以将rxjs Observablesasync keyowrd一起使用,这样可以更有效地解决问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51171049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档