升级Angular后出现ExpressionChangedAfterItHasBeenCheckedError错误如何解决
问题根因
这个ExpressionChangedAfterItHasBeenCheckedError报错是Angular开发模式下的专属校验提示,和core-js无关。触发原因是你上层组件的input标签绑定了[matAutocomplete]="myAutocomplete.autocomplete",但自定义组件内的autocomplete属性是通过@ViewChild获取的:
- 父组件首次执行变更检测时,子组件还未完成模板渲染,
myAutocomplete.autocomplete的值为undefined - 子组件渲染完成后
@ViewChild才会完成赋值,此时该属性值变为MatAutocomplete实例,和变更检测第一阶段的值不一致,因此触发报错
功能正常是因为该错误仅在开发环境抛出用于提示开发者,生产模式会跳过该项校验,且值最终会完成更新,不影响实际运行。
解决方案
方案1:给@ViewChild添加static配置(优先推荐)
你的mat-autocomplete组件没有用*ngIf做条件渲染,直接将@ViewChild配置为静态查询即可,Angular会在变更检测运行前完成属性赋值,从根源避免值的前后不一致。
修改自定义自动完成组件的@ViewChild代码:
// 修改前 @ViewChild('autocomplete') autocomplete: MatAutocomplete; // 修改后 @ViewChild('autocomplete', { static: true }) autocomplete: MatAutocomplete;
方案2:父组件延迟赋值(适用于autocomplete存在条件渲染的场景)
如果你的mat-autocomplete是条件渲染的,无法使用static: true配置,可以在父组件通过AfterViewInit钩子延迟赋值,同时手动通知变更检测:
- 父组件ts文件中引入
ChangeDetectorRef,并获取自定义自动完成组件的引用:
import { ChangeDetectorRef, AfterViewInit, ViewChild } from '@angular/core'; import { MyAutocompleteComponent } from 'xxx'; // 替换为你的组件实际路径 export class ParentComponent implements AfterViewInit { @ViewChild('myAutocomplete') myAutocomplete: MyAutocompleteComponent; autocompleteRef: MatAutocomplete; constructor(private cdr: ChangeDetectorRef) {} ngAfterViewInit() { this.autocompleteRef = this.myAutocomplete.autocomplete; this.cdr.markForCheck(); } }
- 父组件模板修改绑定属性:
<input class="t-myClass" type="text" matInput [formControl]="myFormGroup.controls['myField']" (change)="resetValidity()" [matAutocomplete]="autocompleteRef" #myField>
附加优化建议
给filteredObjects添加初始默认值,避免async管道首次取值时为undefined引发的潜在问题:
// 引入rxjs的of方法 import { of } from 'rxjs'; export class MyAutocompleteComponent implements OnInit, OnChanges, OnDestroy { // 修改初始化代码 filteredObjects: Observable<MyElement[]> = of([]); // 其余代码保持不变 }
内容的提问来源于stack exchange,提问作者phildeg31
相关产品推荐
相关产品推荐

