ChatGPT解决这个技术问题 Extra ChatGPT

ExpressionChangedAfterItHasBeenCheckedError 解释

请向我解释为什么我不断收到此错误:ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.

显然,我只在开发模式下获得它,它不会发生在我的生产版本中,但这很烦人,我根本不明白在我的开发环境中出现错误而不会出现在产品上的好处 - -可能是因为我缺乏了解。

通常,修复很容易,我只是将导致错误的代码包装在 setTimeout 中,如下所示:

setTimeout(()=> {
    this.isLoading = true;
}, 0);

或者使用如下构造函数强制检测更改:constructor(private cd: ChangeDetectorRef) {}

this.isLoading = true;
this.cd.detectChanges();

但是为什么我经常遇到这个错误?我想了解它,以便将来避免这些骇人听闻的修复。

我也面临同样的问题,它只发生在 DEV 上并且只影响我的控制台日志。我没有在项目中引入任何新代码,而是简单地从控制台隐藏/阻止此错误。
来自 Angular 的官方指南 - angular.io/errors/NG0100
您提到的解决方案不是一个hacky,而是一个适当的解决方案。此处描述:blog.angular-university.io/angular-debugging
youtube.com/watch?v=O47uUnJjbJc。请观看 YouTube 视频以获得快速概览和可能的解决方案

s
szaman

我有一个类似的问题。查看 lifecycle hooks documentation,我将 ngAfterViewInit 更改为 ngAfterContentInit 并且它起作用了。


@PhilipEnc 我的问题与 DOM 更改触发的更改有关。当 DOM 发生变化时,QueryList 对象(来自 @ContentChildren 属性)将更新,并且在更新调用它的方法内部更改了双向绑定属性。这造成了我遇到的问题。像上面显示的那样用 setTimeout 将该更改包装到二属性就可以了。谢谢!
在我的情况下,我在 ngAfterContentInit 中放置了一些更改primeng 网格数组值的代码,我将代码放在 ngOnInit 中并且它起作用了。
ngAfterContentChecked 在这里工作,而 ngAfterContentInit 仍然抛出错误。
ngAfterContentChecked 使用但项目加载速度很慢
如果我们尝试在 ngAfterViewInit 之前更改 ngIf 的绑定属性,那么它不会抛出错误。即我们可以在构造函数、ngOnChanges、ngOninit 中设置值而不会出现任何错误。
C
Community

此错误表明您的应用程序中存在真正的问题,因此引发异常是有意义的。

devMode 中,更改检测会在每次常规更改检测运行后添加一个额外的轮次,以检查模型是否已更改。

如果模型在常规和附加变化检测轮次之间发生了变化,这表明要么

变化检测本身已经引起了变化

每次调用方法或 getter 时都会返回不同的值

这两者都很糟糕,因为模型可能永远不会稳定,因此不清楚如何进行。

如果 Angular 在模型稳定之前运行变化检测,它可能会一直运行。如果 Angular 不运行变更检测,那么视图可能不会反映模型的当前状态。

另请参阅What is difference between production and development mode in Angular2?


我怎样才能避免将来看到这个错误?我需要以不同的方式来考虑我的代码,以确保我不会犯同样的错误吗?
通常这是由诸如 ngOnInitngOnChanges 之类的生命周期回调来修改模型引起的(一些生命周期回调允许修改其他人不允许修改的模型,我不记得自己究竟是哪个做或不做)。不要绑定到视图中的方法或函数,而是绑定到字段并更新事件处理程序中的字段。如果您必须绑定到方法,请确保它们始终返回相同的值实例,只要实际上没有更改。变更检测会大量调用这些方法。
这不一定是应用程序的问题。调用 changeRef.detectChanges() 是一种解决方案/抑制错误的事实证明了这一点。这就像在 Angular 1 中修改 $scope.$watch() 内的状态。
我不太了解 Angular 1,但 Angular 2 中的更改检测工作方式完全不同。你是对的,它不一定是一个问题,但通常 cdRef.detectChanges() 只在一些奇怪的边缘情况下是必需的,当你需要它时你应该仔细查看,你理解正确的原因。
如果我的 html 通过 get ClockValue() { return DateTime.TimeAMPM(new Date()) } 绑定到 getter 返回时间为“HH:MM”,它最终会在检测运行时发生变化时跳闸,我该如何解决这个问题?
K
Kevin LeStarge

一旦我了解了 the Angular Lifecycle Hooks 及其与变更检测的关系,就会产生很多理解。

我试图让 Angular 更新绑定到元素 *ngIf 的全局标志,并且试图在另一个组件的 ngOnInit() 生命周期挂钩内更改该标志。

根据文档,在 Angular 已经检测到更改后调用此方法:

在第一个 ngOnChanges() 之后调用一次。

因此更新 ngOnChanges() 内的标志不会启动更改检测。然后,一旦更改检测再次自然触发,标志的值就会发生更改并引发错误。

就我而言,我改变了这个:

constructor(private globalEventsService: GlobalEventsService) {

}

ngOnInit() {
    this.globalEventsService.showCheckoutHeader = true;
}

对此:

constructor(private globalEventsService: GlobalEventsService) {
    this.globalEventsService.showCheckoutHeader = true;
}

ngOnInit() {

}

它解决了问题:)


我的问题是相似的。长时间后我犯了一个错误,并在 ngOnInit 函数和构造函数之外定义了一个变量。这接收来自可观察对象的数据更改,该可观察对象放置在初始化函数中。做了和你一样的事情来修复错误。
到处都非常相似,但是如果 URL 中存在,我试图在加载到片段时滚动 (router.navigate)。此代码最初放置在我收到错误的 AfterViewInit 中,然后我按照您对构造函数的说法移动,但它不尊重片段。移至 ngOnInit 已解决 :) 谢谢!
如果我的 html 通过 get ClockValue() { return DateTime.TimeAMPM(new Date()) } 绑定到 getter 返回时间为“HH:MM”,它最终会在检测运行时发生变化时跳闸,我该怎么办解决这个问题?
同样在这里。还发现如果需要在其他生命周期事件代码之后触发,包装到 setInterval() 中也有效。
得到了一个非常相似的场景,虽然我改变的状态不是布尔标志,而是一些枚举(状态)字段。解决方法是用“ngIf”包装引用这个有问题的状态字段的html,这将检查其他一些已经初始化的字段。
S
Sergey

Angular 运行更改检测,当它发现某些已传递给子组件的值已更改时,Angular 会抛出以下错误:

ExpressionChangedAfterItHasBeenCheckedError click for more

为了纠正这个问题,我们可以使用 AfterContentChecked 生命周期钩子和

import { ChangeDetectorRef, AfterContentChecked} from '@angular/core';

  constructor(
  private cdref: ChangeDetectorRef) { }

  ngAfterContentChecked() {

    this.cdref.detectChanges();

  }

虽然这可能会解决问题,但这不是非常膨胀和过度杀伤 CD 吗?
我认为这是解决由于将值传递给孩子而导致的此错误的唯一答案。谢谢!
@Nicky 是的。每次触摸屏幕时,任何地方都会调用 ngAfterContentChecked()
该解决方案帮助我解决了将更改从子组件传递回 app.components.ts 的问题。谢谢
我们在子组件或父组件中这样做吗?只是遇到同样的问题,并试图更好地理解根本问题。
f
fcdt

我正在使用 ng2-carouselamos(Angular 8 和 Bootstrap 4)

采取这些步骤解决了我的问题:

实现 AfterViewChecked 添加构造函数(private changeDetector : ChangeDetectorRef ) {} 然后 ngAfterViewChecked(){ this.changeDetector.detectChanges(); }


就处理工作而言,这必须要求很高 - 听起来这可能是一个需要速度的应用程序严重减速的真正潜力
A
Arnaud P

更新

我强烈建议先从 the OP's self response 开始:正确考虑在 constructor 中可以做什么与在 ngOnChanges() 中应该做什么。

原来的

这与其说是一个答案,不如说是一个旁注,但它可能会对某人有所帮助。在尝试使按钮的存在取决于表单的状态时,我偶然发现了这个问题:

<button *ngIf="form.pristine">Yo</button>

据我所知,这种语法会导致按钮根据条件从 DOM 中添加和删除。这又导致 ExpressionChangedAfterItHasBeenCheckedError

在我的情况下,解决方法(尽管我没有声称掌握差异的全部含义)是使用 display: none 代替:

<button [style.display]="form.pristine ? 'inline' : 'none'">Yo</button>

我对 ngIf 与样式之间的区别的理解是,ngIf 在条件为真之前不会将 HTML 包含在页面中,因此会稍微减少“页面重量”,而样式技术会导致 HTML 始终是在页面中,并根据 form.pristine 的值简单地隐藏或显示。
您不妨使用 [hidden] 而不是非常冗长的 [style.display] 部分。 :)
为什么不。尽管正如 @Simon_Weaver 在此页面的另一条评论中提到的那样,[hidden] will not always have the same behaviordisplay: none
我在每个按钮中显示了两个带有 *ngIf 的不同按钮(注销/登录),这导致了问题。
构造函数对我来说是正确的地方,推出了一个材料小吃店
e
eper

有一些有趣的答案,但我似乎没有找到一个符合我需求的答案,最接近的是来自@chittrang-mishra,它只指一个特定的功能,而不是像我的应用程序中的几个切换。

我不想使用 [hidden] 来利用 *ngIf 甚至不是 DOM 的一部分,所以我发现以下解决方案可能不是对所有人最好的,因为它抑制错误而不是纠正它,但在我知道最终结果是正确的情况,这对我的应用程序来说似乎没问题。

我所做的是实现 AfterViewChecked,添加 constructor(private changeDetector : ChangeDetectorRef ) {},然后

ngAfterViewChecked(){
  this.changeDetector.detectChanges();
}

我希望这对其他人有所帮助,因为许多其他人已经帮助了我。


这不会触发无限变化检测循环吗?我的意思是,您在检查后正在检测更改。
@ManuelAzar 显然不是。这是唯一对我有用的解决方案。我的控制台终于安静下来了。我厌倦了所有这些无关的变更检测“错误”。
抑制错误是什么意思?不是changeDetector检测到的变化吗?
@ManuelAzar 没有无限循环,因为 ngAfterViewChecked 在组件生命周期中只调用一次。触发变更检测周期不会重新启动组件生命周期,因此不会再次调用 ngAfterViewChecked,除非从头开始重新渲染组件。 (请注意,其他一些挂钩,例如 ngDoCheck,将由额外的变更检测周期触发,因为它们会误导性地挂钩到变更检测周期而不是直接连接到组件生命周期。在 ngDoCheck 中使用 detectChanges() 会导致一个无限循环。)
T
Tom

请按照以下步骤操作:

1. 通过从@angular/core 导入来使用'ChangeDetectorRef',如下所示:

import{ ChangeDetectorRef } from '@angular/core';

2.在constructor()中实现如下:

constructor(   private cdRef : ChangeDetectorRef  ) {}

3. 将以下方法添加到您在单击按钮等事件上调用的函数中。所以它看起来像这样:

functionName() {   
    yourCode;  
    //add this line to get rid of the error  
    this.cdRef.detectChanges();     
}

M
Michael

就我而言,我在运行测试时在我的规范文件中遇到了这个问题。

我必须将 ngIf 改为 [hidden]

<app-loading *ngIf="isLoading"></app-loading>

<app-loading [hidden]="!isLoading"></app-loading>

此处的区别在于 *ngIf 更改 DOM,在页面中添加和删除元素,而 [hidden] 更改项目的可见性,但不将其从 DOM 中删除。
但是,这并没有真正解决真正的问题......?
当这些隐藏字段中的一个发生更改时,这触发了我所有的验证器,而不是一个漂亮的网站,可以看到所有东西都是红色的!
M
Massimiliano Kraus

我面临着同样的问题,因为我的组件中的一个数组中的值正在发生变化。但我没有检测值变化的变化,而是将组件变化检测策略更改为 onPush(它将检测对象变化而不是值变化)。

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush
    selector: -
    ......
})

这似乎适用于动态添加/删除控件..有什么缺点吗?
在我手头的情况下就像一个魅力,谢谢!一个组件绑定到一个“全局”对象,该对象在其他地方被更改并导致错误发生。此组件已经有一个更新处理程序,用于更新绑定对象时,此事件处理程序现在调用 changeDetectorRef.detectChanges() 结合 ChangeDetectionStrategy.OnPush 这可以按需要正常工作而不会出现错误。
@RicardoSaracino 你有没有发现任何缺点?我想知道同样的事情。我知道更改检测 OnPush 是如何工作的,但想知道是否存在我可能遗漏的问题。我不想绕回去。
@RicardoSaracino,是的,它有一些缺点,你可以参考这个详细的链接blog.angular-university.io/onpush-change-detection-how-it-works
@BernoulliIT 谢谢,我很高兴它对你有用。
A
ATHER

参考文章https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

因此,变更检测背后的机制实际上是以同步执行变更检测和验证摘要的方式工作的。这意味着,如果我们异步更新属性,则在验证循环运行时不会更新值,也不会出现 ExpressionChanged... 错误。我们收到此错误的原因是,在验证过程中,Angular 看到的值与其在变更检测阶段记录的值不同。所以为了避免这种情况......

1)使用changeDetectorRef

2) 使用 setTimeOut。这将在另一个 VM 中作为宏任务执行您的代码。 Angular 在验证过程中不会看到这些更改,您也不会收到该错误。

 setTimeout(() => {
        this.isLoading = true;
    });

3)如果您真的想在同一个VM上执行您的代码,请使用

Promise.resolve(null).then(() => this.isLoading = true);

这将创建一个微任务。微任务队列是在当前同步代码执行完毕后处理的,因此属性的更新将在验证步骤之后发生。


您可以将选项#3 与样式表达式一起使用吗?我有一个应该最后评估的高度样式表达式,因为它基于注入的内容。
抱歉刚刚看到你的评论,是的,我看不出有什么理由不这样做。所以这也应该适用于风格变化。
S
Safal Pillai

尝试了上面建议的大多数解决方案。在这种情况下,只有这对我有用。我正在使用 *ngIf 根据 api 调用来切换角度材料的不确定进度条,它正在抛出 ExpressionChangedAfterItHasBeenCheckedError

在有问题的组件中:

constructor(
    private ngZone: NgZone,
    private changeDetectorRef: ChangeDetectorRef,
) {}

ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
        this.appService.appLoader$.subscribe(value => {
            this.loading = value;
            this.changeDetectorRef.detectChanges();
        });
    });
}

诀窍是使用 ngzone 绕过角度组件的变化检测。

PS:不确定这是否是一个优雅的解决方案,但使用 AfterContentChecked 和 AfterViewChecked 生命周期钩子必然会引发性能问题,因为您的应用程序会因为它被多次触发而变得更大。


偶然发现处理相同用例的问题。万分感谢。
C
Community

@HostBinding 可能是此错误的一个令人困惑的来源。

例如,假设您在组件中有以下主机绑定

// image-carousel.component.ts
@HostBinding('style.background') 
style_groupBG: string;

为简单起见,假设此属性通过以下输入属性更新:

@Input('carouselConfig')
public set carouselConfig(carouselConfig: string) 
{
    this.style_groupBG = carouselConfig.bgColor;   
}

在父组件中,您以编程方式将其设置在 ngAfterViewInit

@ViewChild(ImageCarousel) carousel: ImageCarousel;

ngAfterViewInit()
{
    this.carousel.carouselConfig = { bgColor: 'red' };
}

这是发生的事情:

您的父组件已创建

ImageCarousel 组件被创建,并分配给 carousel(通过 ViewChild)

在 ngAfterViewInit() 之前我们无法访问轮播(它将为空)

我们分配配置,设置 style_groupBG = 'red'

这反过来在主机 ImageCarousel 组件上设置背景:红色

该组件由您的父组件“拥有”,因此当它检查更改时,它会在 carousel.style.background 上发现更改,并且不够聪明,无法知道这不是问题,因此会引发异常。

一种解决方案是引入另一个包装器 div 内部 ImageCarousel 并在其上设置背景颜色,但是您不会获得使用 HostBinding 的一些好处(例如允许父级控制对象的完整边界)。

更好的解决方案是在父组件中设置配置后添加detectChanges()。

ngAfterViewInit()
{
    this.carousel.carouselConfig = { ... };
    this.cdr.detectChanges();
}

这可能看起来很明显,并且与其他答案非常相似,但存在细微差别。

考虑在开发后期才添加 @HostBinding 的情况。突然你得到这个错误,它似乎没有任何意义。


n
nircraft

这是我对正在发生的事情的想法。我还没有阅读文档,但我确信这是显示错误的部分原因。

*ngIf="isProcessing()" 

使用 *ngIf 时,它会在每次条件更改时通过添加或删除元素来物理更改 DOM。因此,如果条件在呈现到视图之前发生变化(这在 Angular 的世界中很有可能),就会引发错误。请参阅开发模式和生产模式之间的说明 here

[hidden]="isProcessing()"

使用 [hidden] 时,它不会实际更改 DOM,而只是从视图中隐藏 element,很可能在后面使用 CSS。该元素仍然存在于 DOM 中,但根据条件的值不可见。这就是使用 [hidden] 时不会发生错误的原因。


如果 isProcessing() 做同样的事情,您必须使用 !isProcessing() 作为 [hidden]
hidden 没有“在后面使用 CSS”,它是一个常规的 HTML 属性。 developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/…
C
Community

调试提示

这个错误可能会非常令人困惑,并且很容易对它发生的确切时间做出错误的假设。我发现在受影响的组件中的适当位置添加大量这样的调试语句很有帮助。这有助于理解流程。

在这样的父 put 语句中(确切的字符串 'EXPRESSIONCHANGED' 很重要),但除此之外,这些只是示例:

    console.log('EXPRESSIONCHANGED - HomePageComponent: constructor');
    console.log('EXPRESSIONCHANGED - HomePageComponent: setting config', newConfig);
    console.log('EXPRESSIONCHANGED - HomePageComponent: setting config ok');
    console.log('EXPRESSIONCHANGED - HomePageComponent: running detectchanges');

在子/服务/计时器回调中:

    console.log('EXPRESSIONCHANGED - ChildComponent: setting config');
    console.log('EXPRESSIONCHANGED - ChildComponent: setting config ok');

如果您也手动运行 detectChanges 添加日志记录:

    console.log('EXPRESSIONCHANGED - ChildComponent: running detectchanges');
    this.cdr.detectChanges();

然后在 Chrome 调试器中按“EXPRESSIONCHANGES”过滤。这将准确地向您展示所有设置的流程和顺序,以及 Angular 在什么时候抛出错误。

https://i.stack.imgur.com/JuhhE.png

您也可以单击灰色链接来放置断点。

如果您在整个应用程序中具有类似名称的属性(例如 style.background),则需要注意的另一件事是确保您正在调试您认为的属性 - 通过将其设置为模糊的颜色值。


t
tedw

如果您在 ngAfterViewInit() 中触发 EventEmitter 时看到 ExpressionChangedAfterItHasBeenCheckedError,那么您可以在创建 EventEmitter 时传递 true 以使其在当前更改检测周期后异步发出。

@Component({
  ...
})
export class MyComponent implements AfterViewInit {
  // Emit asynchronously to avoid ExpressionChangedAfterItHasBeenCheckedError
  @Output() valueChange = new EventEmitter<number>(true);

  ...

  ngAfterViewInit(): void {
    ...
    this.valueChange.emit(newValue);
    ...
  }

}

n
nircraft

当我添加 *ngIf 时,我的问题很明显,但这不是原因。该错误是由于更改 {{}} 标记中的模型,然后稍后尝试在 *ngIf 语句中显示更改后的模型引起的。这是一个例子:

<div>{{changeMyModelValue()}}</div> <!--don't do this!  or you could get error: ExpressionChangedAfterItHasBeenCheckedError-->
....
<div *ngIf="true">{{myModel.value}}</div>

为了解决此问题,我将调用 changeMyModelValue() 的位置更改为更有意义的位置。

在我的情况下,我希望在子组件更改数据时调用 changeMyModelValue()。这需要我在子组件中创建并发出一个事件,以便父组件可以处理它(通过调用 changeMyModelValue()。请参阅 https://angular.io/guide/component-interaction#parent-listens-for-child-event


S
Sandeep K Nair

使用 rxjs 对我有用的解决方案

import { startWith, tap, delay } from 'rxjs/operators';

// Data field used to populate on the html
dataSource: any;

....

ngAfterViewInit() {
  this.yourAsyncData.
      .pipe(
          startWith(null),
          delay(0),
          tap((res) => this.dataSource = res)
      ).subscribe();
}

有问题的代码是什么?这里的解决方案是什么?
嗨@mkb,问题是ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.在 DOM 更改时触发值更改时发生
嗨,我的意思是你在这里做了什么来克服这个问题。你之前根本没用过rxjs,还是加了delay(),还是加了startWith()?我已经将 rxjs 与各种 rxjs 方法一起使用,但仍然出现错误,我希望能解决这个问题:(
添加的 delay 使错误消失。它的工作原理与 setTimeout 类似。
n
nircraft

我在 Ionic3 中遇到了这种错误(它使用 Angular 4 作为其技术堆栈的一部分)。

对我来说,它是这样做的:

<ion-icon [name]="getFavIconName()"></ion-icon>

因此,我试图根据屏幕运行的模式有条件地将 ion-icon 的类型从 pin 更改为 remove-circle

我猜我将不得不添加一个 *ngIf


D
Demodave

对于我的问题,我正在阅读 github -“ExpressionChangedAfterItHasBeenCheckedError 在 afterViewInit 中更改组件'非模型'值时”并决定添加 ngModel

<input type="hidden" ngModel #clientName />

它解决了我的问题,我希望它可以帮助某人。


该网站上的哪个位置说要添加 ngModel。您能否详细说明为什么这会有所帮助?
当我追踪这个问题时,它引导我调查链接。阅读文章后,我添加了属性并解决了我的问题。如果有人遇到同样的问题,这将很有帮助。
M
Mahesh

就我而言,我在 LoadingService 中有一个带有 BehavioralSubject isLoading 的异步属性

使用 [hidden] 模型有效,但 *ngIf 失败

    <h1 [hidden]="!(loaderService.isLoading | async)">
        THIS WORKS FINE
        (Loading Data)
    </h1>

    <h1 *ngIf="!(loaderService.isLoading | async)">
        THIS THROWS ERROR
        (Loading Data)
    </h1>

O
O-9

我在 RxJS/Observables 和静态模拟数据之间遇到了这个问题。起初,我的应用程序使用静态模拟数据,在我的例子中是数据数组

html是这样的:

*ngFor="let x of myArray?.splice(0, 10)"

所以这个想法是只显示来自 myArray 的最多 10 个元素。 splice() 获取原始数组的副本。据我所知这在 Angular 中非常好

然后我将数据流更改为 Observable 模式,因为我的“真实”数据来自 Akita(一个状态管理库)。这意味着我的 html 变成了:

*ngFor="let x of (myArray$ | async)?.splice(0, 10)"

其中 myArray$ 是 Observable<MyData[]> 的 [was] 类型,模板中的这种数据操作是导致错误发生的原因。不要对 RxJS 对象这样做。


S
Saeed Sharman

setTimeout 或 delay(0) 如何解决这个问题?

这就是上面的代码解决问题的原因:

The initial value of the flag is false, and so the loading indicator will NOT be displayed initially

ngAfterViewInit() gets called, but the data source is not immediately called, so no modifications of the loading indicator will be made synchronously via ngAfterViewInit()

Angular then finishes rendering the view and reflects the latest data changes on the screen, and the Javascript VM turn completes

One moment later, the setTimeout() call (also used inside delay(0)) is triggered, and only then the data source loads its data

the loading flag is set to true, and the loading indicator will now be displayed

Angular finishes rendering the view, and reflects the latest changes on the screen, which causes the loading indicator to get displayed

这次没有发生错误,因此修复了错误消息。

来源:https://blog.angular-university.io/angular-debugging/


r
retr0

我希望这对来到这里的人有所帮助:我们以下列方式在 ngOnInit 中进行服务调用,并使用变量 displayMain 来控制将元素安装到 DOM。

组件.ts

  displayMain: boolean;
  ngOnInit() {
    this.displayMain = false;
    // Service Calls go here
    // Service Call 1
    // Service Call 2
    // ...
    this.displayMain = true;
  }

和component.html

<div *ngIf="displayMain"> <!-- This is the Root Element -->
 <!-- All the HTML Goes here -->
</div>

s
shreekar hegde

我收到此错误是因为我在 component.html 中使用了一个未在 component.ts 中声明的变量。一旦我删除了 HTML 中的部分,这个错误就消失了。


M
Muneem Habib

我收到此错误是因为我在模态中调度 redux 操作,而当时没有打开模态。在模态组件收到输入的那一刻,我正在调度动作。所以我把 setTimeout 放在那里,以确保打开模式,然后分配动作。


E
Eric

我的问题是我在加载这个检查后正在更改的对象时打开了一个 Ngbmodal 弹出窗口。我能够通过打开 setTimeout 内的模式弹出窗口来解决它。

setTimeout(() => {
  this.modalReference = this.modalService.open(this.modal, { size: "lg" });
});

d
danday74

当一个值在同一个变化检测周期中变化不止一次时,会发生此错误。我遇到了一个 TypeScript getter 的问题,它的返回值变化非常频繁。要解决此问题,您可以限制一个值,使其在每个更改检测周期中只能更改一次,如下所示:

import { v4 as uuid } from 'uuid'

private changeDetectionUuid: string
private prevChangeDetectionUuid: string
private value: Date

get frequentlyChangingValue(): any {
  if (this.changeDetectionUuid !== this.prevChangeDetectionUuid) {
    this.prevChangeDetectionUuid = this.changeDetectionUuid
    this.value = new Date()
  }
  return this.value
}

ngAfterContentChecked() {
  this.changeDetectionUuid = uuid()
}

HTML:

<div>{{ frequentlyChangingValue }}</div>

这里的基本做法是,每个变更检测周期都有自己的 uuid。当 uuid 发生变化时,您就知道您处于下一个循环中。如果循环已更改,则更新该值并返回它,否则只返回与此循环先前返回的相同的值。

这确保了每个循环只返回一个值。鉴于更改检测周期如此频繁地发生,这对于频繁更新值非常有效。

为了生成 uuid,我使用了 uuid npm 模块,但您可以使用任何生成唯一随机 uuid 的方法。


G
Gabriel Arghire

将 static: true 添加到 @ViewChild 装饰器

@ViewChild(UploadComponent, { static: true }) uploadViewChild: UploadComponent;

u
user998548

解决方案...服务和 rxjs...事件发射器和属性绑定都使用 rxjs..您最好自己实现它,更多控制,更容易调试。请记住,事件发射器正在使用 rxjs。简单地说,创建一个服务并在一个 observable 中,让每个组件订阅 tha 观察者,并根据需要传递新值或 cosume 值


这不仅不能回答问题,而且还是很糟糕的建议。伙计们,请不要仅仅因为遇到 Angular 的 CD 错误就自己重新实现 rxjs。 :)

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅