为何仅使用@Input()时触发ExpressionChangedAfterItHasBeenCheckedError?
首先明确该错误的官方定义:
Angular throws an ExpressionChangedAfterItHasBeenCheckedError when an expression value has been changed after change detection has completed.
(中文翻译:Angular 会在变更检测完成后表达式值发生变化时抛出ExpressionChangedAfterItHasBeenCheckedError错误)
你遇到的两个示例之所以一个报错一个不报错,核心差异在于被修改的父组件值是否与子组件的@Input()属性存在绑定关系:
无错误的示例中,子组件触发事件修改的父组件值,并未作为子组件的输入属性进行绑定。Angular在当前变更检测周期内,仅会校验父组件模板、子组件输入属性的初始同步值。由于被修改的父值未与子组件输入挂钩,在变更检测的二次验证阶段,Angular不会检测到值的不一致,因此不会触发错误。
报错的示例中,子组件触发事件修改的父组件值,正是子组件声明的
@Input()属性。Angular的变更检测流程为:先将父组件的该值同步至子组件输入,随后执行子组件的事件回调修改了父组件的这个值。在本轮变更检测的二次验证环节,Angular会再次对比子组件输入属性与父组件对应值,发现二者已不一致——这违反了“变更检测完成后表达式值不可变更”的规则,因此抛出了ExpressionChangedAfterItHasBeenCheckedError。
内容的提问来源于stack exchange,提问作者ruddnisrus

