一个|一个 ExpressionChangedAfterItHasBeenCheckedError 错误的解决过程
问题描述
我的 Component 里有一个 selectedPane 字段(第56行),作为数据源显示在 div 标签里(代码第47行):
文章图片
代码第 51 行,我使用 @ViewChild 这个 query,将第 45 行的 div 元素,查询出来并通过 52 行的 set 函数,赋给 this.selectedPane.
运行时收到这条错误消息:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: ''. Current value: 'undefined'.
文章图片
问题分析
从调试器里能看出,旧的 value 是 "", 新的 value 是 undefined,因此抛出异常:
文章图片
if (ngDevMode && isInCheckNoChangesMode()) {
// View engine didn't report undefined values as changed on the first checkNoChanges pass
// (before the change detection was run).
const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;
if (!devModeEqual(oldValueToCompare, value)) {
const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);
throwErrorIfNoChangesMode(oldValue =https://www.it610.com/article/== NO_CHANGE, details.oldValue, details.newValue, details.propName);
}
// There was a change, but the `devModeEqual` decided that the change is exempt from an error.
// For this reason we exit as if no change. The early exit is needed to prevent the changed
// value to be written into `LView` (If we would write the new value that we would not see it
// as change on next CD.)
return false;
}
这个错误在 Angular 官网的这个视频里有详细的解释:
如果在 Angular 框架执行完变更检测之后,再修改属性值,比如在
ngAfterViewInit
或者本文例子的 set 函数里,就会抛出这个异常。文章图片
解决方案 一种 StackOverflow 上经常提到的解决方案就是,使用
异步更新
, 将值的修改推迟到下一次变更检测周期中执行:文章图片
使用
setTimeout
配合延迟为 0
的调用方式,使得这个更新对应的检测,发生在下一次浏览器的宏任务队列中。文章图片
【一个|一个 ExpressionChangedAfterItHasBeenCheckedError 错误的解决过程】采用立即执行的
Promise
可以达到同样的效果:Promise.resolve().then(() => this.loading false);
![](https://img-blog.csdnimg.cn/img_convert/25322fe43c081d144f8af96da180ec72.png)![](https://img-blog.csdnimg.cn/img_convert/7b4957cd8b42d1ec79e0bd7d16271953.png)错误消失了:
![](https://img-blog.csdnimg.cn/img_convert/bea6d17d6dbde5f7ae5e3c136baa2afe.png)另一种解决方案是,在 set 函数里修改了属性值之后,立即`手动`触发一次 change detection:
![](https://img-blog.csdnimg.cn/img_convert/2238d967cfff2194184077f41e21d5e8.png)能实现同样的效果:
![](https://img-blog.csdnimg.cn/img_convert/31094ef2caa2e58c89a091e4c888e735.png)
推荐阅读
- 关于|关于 ng-template 通过 @input 传入另一个 Component 不能工作的问题调试
- LeetCode编程题解法汇总|力扣解法汇总41-缺失的第一个正数
- 手把手带你实现一个萌芽版的Spring容器
- 从零开始,开发一个|从零开始,开发一个 Web Office 套件(6)(光标 & Click 事件)
- 肝了两周,我做了一个面试刷题小程序
- KTL|KTL 一个支持C++14编辑公式的K线技术工具平台 - 第四版,稳定支持Qt5编程,zqt5语法升级,MA函数提升性能1000%,更多公式算法的内置优化实现。
- javascript|vue从零搭建一个前中后台权限管理模板
- 中间件|Apache Member、ALC Beijing 发起人姜宁(一个人走的很快,但是一群人能走得更远)
- 大话开源|ALC北京发起人 姜宁(通过开放与协作,我们可以实现一个人想都不敢想的事情 I OpenTEKr 大话开源 Vol.6)
- ASF|ASF 孵化器导师姜宁(开源不是简单的代码开放,是依托项目构建一个共同体)