问题描述我的Component中有一个selectedPane字段(第56行),显示在div标签中作为数据源(代码第47行):代码第51行,我使用@ViewChild这个查询,查询第45行的div元素,通过第52行的set函数赋值给this.selectedPane,运行时收到如下错误信息:ERRORError:ExpressionChangedAfterItHasBeenCheckedError:Expressionhaschangedafteritwaschecked。先前值:''。当前值:“未定义”。问题分析从debugger可以看出旧值为"",新值未定义,所以抛出异常:if(ngDevMode&&isInCheckNoChangesMode()){//Viewenginedidn'treportundefinedvalues在第一次checkNoChanges传递时更改//(在运行更改检测之前)。constoldValueToCompare=oldValue!==NO_CHANGE?旧值:未定义;如果(!devModeEqual(oldValueToCompare,value)){constdetails=getExpressionChangedErrorDetails(lView,bindingIndex,oldValueToCompare,value);throwErrorIfNoChangesMode(oldValue===NO_CHANGE,details.oldValue,details.newValue,details.propName);}//发生了变化,但`devModeEqual`决定该变化不会出错。//出于这个原因,我们退出,就好像没有改变一样。需要提前退出以防止将更改的//值写入`LView`(如果我们写入新值,我们将不会在下一张CD上看到它//作为更改。)返回false;}这个错误在Angular官网这个视频里有详细的解释:如果在Angular框架进行变更检测之后修改属性值,比如在ngAfterViewInit或者本文例子的set函数中,就会出现这个异常抛出。StackOverflow上经常提到该解决方案。解决方法是使用异步更新,将值的修改推迟到下一个变化检测周期:使用setTimeout调用方法,延迟为0,这样这个更新对应的检测就会发生在下一个浏览器的宏任务队列中.使用立即执行的Promise可以达到同样的效果:Promise.resolve().then(()=>this.loadingfalse);报错消失:另一种解决方法是在set函数中修改属性值后,立即手动触发一次变化检测:可以达到同样的效果:
