Angular自定义双向绑定中Change EventEmitter为何触发两次?
解决Angular自定义双向绑定EventEmitter触发两次的问题
嗨,我之前也碰到过一模一样的问题,大概率是这几个常见坑导致的,咱们一步步排查解决:
先检查父组件模板的重复绑定
最容易踩的雷就是同时使用双向绑定语法 [(counter)] 和单独绑定 (counterChange) 事件。举个例子,如果你的父组件模板是这么写的:
<app-custom-counter [(counter)]="parentCount" (counterChange)="handleCounterChange($event)"></app-custom-counter>
这时候handleCounterChange会被触发两次——因为[(counter)]本身就是[counter]="parentCount" + (counterChange)="parentCount=$event"的语法糖,额外加的(counterChange)相当于多了一次监听,自然会触发两次。解决方法很简单:去掉其中一个绑定,要么只用双向绑定,要么分开写单向输入和输出(但完全没必要重复绑定)。
再排查组件内部的实现逻辑
另一个高频原因是在输入属性的setter里手动触发了counterChange.emit(),比如这种错误写法:
export class CustomCounterComponent { counterValue = 0; @Input() set counter(val: number) { this.counterValue = val; this.counterChange.emit(val); // 这里就是问题所在! } @Output() counterChange = new EventEmitter<number>(); increment() { this.counterValue++; this.counterChange.emit(this.counterValue); // 这里又触发一次 } }
当父组件通过双向绑定更新值时,setter会被调用并emit一次;组件内部点击按钮修改值时又emit一次,直接导致了两次触发。
正确的做法是只在组件内部主动修改值的时候才触发emit,输入属性的setter只负责同步内部值,不要触发事件:
export class CustomCounterComponent { private _counterValue = 0; @Input() get counter(): number { return this._counterValue; } set counter(val: number) { this._counterValue = val; // 这里不要emit!父组件传值过来不需要触发事件 } @Output() counterChange = new EventEmitter<number>(); increment() { this._counterValue++; this.counterChange.emit(this._counterValue); // 只有内部修改时触发 } decrement() { this._counterValue--; this.counterChange.emit(this._counterValue); } }
额外检查生命周期钩子
如果你在ngOnChanges钩子中处理了counter属性的变化,并且在里面调用了counterChange.emit(),也会导致重复触发。比如:
ngOnChanges(changes: SimpleChanges) { if (changes['counter']) { this.counterValue = changes['counter'].currentValue; this.counterChange.emit(this.counterValue); // 这里会和内部修改的emit重复 } }
这种情况同样要去掉ngOnChanges里的emit,只保留内部修改时的触发逻辑即可。
按照这几步排查,应该就能解决触发两次的问题啦!
内容的提问来源于stack exchange,提问作者Sharikov Vladislav
相关产品推荐
相关产品推荐

