为何Angular在自定义ControlValueAccessor组件ngOnDestroy后调用registerOnChange
Angular 12+ 自定义表单控件销毁后触发registerOnXX方法问题说明
根因
该行为是Angular 12版本对表单模块的优化更新引入的官方设计:当承载自定义表单控件的路由跳转、组件销毁时,Angular表单系统会先触发自定义组件的ngOnDestroy生命周期,再调用registerOnChange、registerOnTouched传入空函数覆盖原有回调,用于清理内存、避免回调残留导致的内存泄漏。
可行解决方案
你可以根据业务场景选择以下任意一种方案解决空引用报错:
- 方案1:给回调逻辑增加空值防御判断
在registerOnChange、registerOnTouched的实现逻辑中,访问CodeMirror实例前先判断实例是否存在,不存在直接终止执行,示例代码如下:registerOnTouched(fn: () => void): void { this.onTouched = () => { // 增加空值判断 if (!this.codeMirrorInstance) return; fn(); }; } - 方案2:调整ngOnDestroy的执行顺序
销毁CodeMirror实例前,先把自定义控件的onChange、onTouched回调置为空函数,再执行实例销毁逻辑:ngOnDestroy(): void { // 先清空回调,避免后续被调用时报错 this.onChange = () => {}; this.onTouched = () => {}; // 再销毁编辑器实例 this.codeMirrorInstance?.destroy(); this.codeMirrorInstance = null; } - 方案3:全量使用可选链访问编辑器实例
所有用到CodeMirror实例的代码位置统一使用可选链操作符?.,即使实例为null也不会抛出空引用错误:// 示例:所有访问实例的位置都加可选链 this.codeMirrorInstance?.setValue('');
内容的提问来源于stack exchange,提问作者Trevor
相关产品推荐
相关产品推荐

