ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked,angular

Angular视图渲染错误解析
本文探讨了Angular中常见的视图渲染错误“ExpressionChangedAfterItHasBeenCheckedError”,解释了其产生的原因,并提供了三种实用的解决方案,包括使用AfterViewChecked生命周期钩子、setTimeout延迟执行和在HTML中使用async指令。

 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'dateObj: undefined'. Current value: 'dateObj: [object Object]'.

大概意思:在内容改变的时候视图已经渲染了,试图渲染时前一个值与当前值不一样。

解决办法:

     1、将需要渲染的值放在AterviewInint中;进行初始化;

     2、用setTimeOut(()=>{},0),延迟程序执行;

    3、在html中添加async,for example

    <img  [src]="imgurl  | async" alt="无图片">

具体原因请查看如下网址:

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

 

Angular 中,`ExpressionChangedAfterItHasBeenCheckedError` 是一个常见的错误,它通常出现在开发模式下,表示 Angular 在变更检测过程中发现某个绑定表达式的值在检查之后发生了变化。这种行为可能破坏 Angular 的单向数据流机制,导致难以调试的问题。 ### 错误分析 该错误提示信息如下: ``` ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'attachment: ', Current value: 'attachment: [object Object]' ``` 这表明 `attachment` 属性在 Angular 完成变更检测后又发生了变化。Angular 在开发模式下会执行两次变更检测以确保数据一致性,因此任何在第一次检查之后修改绑定值的行为都会触发此错误[^2]。 ### 解决方案 #### 1. 使用 `ChangeDetectorRef` 手动触发变更检测 通过注入 `ChangeDetectorRef` 并调用其 `markForCheck()` 方法,可以显式告知 Angular 某个组件需要重新进行变更检测。这种方法适用于 OnPush 变更检测策略的组件。 ```typescript import { Component, ChangeDetectorRef, OnInit } from '@angular/core'; @Component({ selector: 'app-example', template: `<div>Attachment: {{ attachment }}</div>` }) export class ExampleComponent implements OnInit { attachment: any; constructor(private cdr: ChangeDetectorRef) {} ngOnInit() { // 模拟异步操作 setTimeout(() => { this.attachment = { name: 'file.pdf' }; this.cdr.markForCheck(); // 手动标记为需要检查 }, 0); } } ``` #### 2. 使用 `setTimeout` 推迟赋值 将属性赋值放入 `setTimeout` 中,可以将其推迟到当前任务队列结束后再执行,从而避免在变更检测阶段中途修改绑定值。 ```typescript ngOnInit() { setTimeout(() => { this.attachment = { name: 'file.pdf' }; }); } ``` #### 3. 在 `ngAfterViewInit` 或 `ngAfterContentInit` 生命周期钩子中处理 某些情况下,数据绑定依赖于视图或内容初始化完成后的操作。此时可以在 `ngAfterViewInit` 或 `ngAfterContentInit` 中更新绑定值,确保这些值不会在变更检测期间被意外修改[^4]。 ```typescript ngAfterViewInit() { this.attachment = { name: 'file.pdf' }; } ``` #### 4. 避免在模板中直接使用对象或函数调用 如果在模板中使用了返回对象或复杂结构的方法(如 `getAttachment()`),每次变更检测都会重新计算该方法的结果,可能导致 `ExpressionChangedAfterItHasBeenCheckedError`。应尽量在组件类中预先计算好这些值并绑定简单类型。 ```html <!-- 不推荐 --> <div>{{ getAttachment() }}</div> <!-- 推荐 --> <div>{{ attachmentName }}</div> ``` ```typescript ngOnInit() { this.attachmentName = this.getAttachment().name; } ``` #### 5. 使用 `OnPush` 变更检测策略 对于那些输入属性较少且不频繁变化的组件,可以考虑使用 `OnPush` 策略,这样 Angular 只会在输入属性发生引用变化时才进行变更检测,减少不必要的检查次数。 ```typescript @Component({ selector: 'app-example', template: `<div>Attachment: {{ attachment }}</div>`, changeDetection: ChangeDetectionStrategy.OnPush }) export class ExampleComponent { @Input() attachment: any; } ``` --- ### 总结 `ExpressionChangedAfterItHasBeenCheckedError` 主要是因为 Angular 在变更检测完成后发现绑定值发生变化。解决此类问题的关键在于理解 Angular 的变更检测机制,并合理利用生命周期钩子、`ChangeDetectorRef` 和异步操作来控制数据更新时机。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值