共计 1567 个字符,预计需要花费 4 分钟才能阅读完成。
驰名的 select2
终于有热心的大牛构建了 angular
版本,并命名为 ng-select2
。但(猜测) 因为其外围的代码依赖于 jquery
, 所以在联合formControl
应用时,会产生如下异样:Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'ng-pristine': 'true'. Current value: 'false'.
情景再现
比方咱们有以下组件树:
一个一般的 A 组件,一个能够实现了 ControlValueAccessor
接口并申明为 FormControl
的 B 组件,一个援用的 ng-select2
组件。
其中 A 组件蕴含 B 组件、B 组件又蕴含 ng-select2
组件。
ng-select2
组件中的数据列表是通过资源申请失去的列表,所以是异步数据,B 组件 V 层示例如下:
<ng-select2
[value]="datum"
[data]="data"
(valueChanged)="onChanged($event)"
</ng-select2>
B 获取 select2 应用的数据列表 data 示例代码如下:
ngOnInit(): void {this.service.getAll()
.subscribe(data => {
// 在这设置 ng-select2 的数据列表
this.data = data;
});
}
此时在 A 组件将会产生如下谬误:Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value for 'ng-pristine': 'true'. Current value: 'false'.
起因猜测
咱们晓得,因为在大牛们会具体的解释异样产生的起因,所以解决问题的第一步也是最重要的一步便是翻译:严重错误:表达式被检测结束当前却产生了变更谬误:当表达式被检测结束当前却又产生了变更。检测结束时,检测的 'ng-pristine' 的值为 'true'. 以后值为:'false'
。
同时 pristine
可译为 原始的
。
所以我猜错主大略是如下产生的:
也就是说:将 A 组件在渲染结束的状况下,发现 FormControl
的值产生了变动,则会产生 ExpressionChangedAfterItHasBeenCheckedError
异样。
解决办法
ng-select2 的官网 demo 中给出了当列表值异步时的解决方案,但遗憾的是该办法同样会引发上述异样。
该异样产生的次要起因是因为 A 组件处于渲染结束,使得 A 中做为 FormControl 的组件 B 同样处于 tHasBeenChecked
状态,所以解决该问题也能够如下着手:
如上图所示,当组件 B 在接管到异步数据时,为了避免其子组件 ng-select2
进行数据弹射时 A 组件处于 渲染结束
状态,咱们在此手动的触发从新渲染所有组件的办法。此时将 A 组件接管到最新的值时,其状态处于 渲染中
,当然也就不会呈现HasBeenChecked 异样
了。
代码如下:
constructor(private service: Service,
private changeDetectorRef: ChangeDetectorRef) {
}
ngOnInit(): void {this.service.getAll()
.subscribe(data => {
// 在这设置 ng-select2 的数据列表
this.data = data;
// 手动调用组件渲染办法,从新渲染各组件
this.changeDetectorRef.detectChanges();});
总结
排错的路千万条,翻译、瞎猜第一条。