Angular9中EventEmitter无法正常emit携带KeyValuePair数组属性的对象
问题根因
该问题的核心是数组为引用类型,你 emit 的对象中 predefinedParameters 传递的是原数组的引用,若有其他订阅者(比如绑定了该 Output 事件的父组件)在处理逻辑中修改了这个数组,会导致所有拿到该引用的地方都感知到变更。你看到的控制台打印结果异常,是因为浏览器控制台打印对象为懒加载模式,点开查看属性时读取的是修改后的最新值,所以显示数组为空。
解决方案
1. emit 时传入数组拷贝,切断引用关联
因为你的 KeyValuePair 是简单值类型,做浅拷贝即可解决引用互相影响的问题,同时建议你主动使用定义好的 SelectedApiCall 构造函数创建实例,避免字面量隐式类型转换的潜在问题:
// 原字面量创建逻辑 // let selectedApiCall = { // identifier: identifier, // predefinedParameters: parametersKeyValuePair // } // 修改为构造函数创建+数组浅拷贝 const selectedApiCall = new SelectedApiCall( identifier, [...parametersKeyValuePair] // 展开运算符做浅拷贝,也可替换为 parametersKeyValuePair.slice() );
2. 移除不合理的内部订阅
@Output 装饰的 EventEmitter 设计用途是给父组件监听事件,不建议在组件内部订阅。如果你需要在 emit 后执行内部逻辑,直接把逻辑写到 emit 语句之后即可,避免多播逻辑混乱。
3. 可选:检查父组件事件处理逻辑
如果父组件的事件处理函数中确实有清空/修改 predefinedParameters 数组的操作,要么调整父组件逻辑使用拷贝后的数据修改,要么保持 emit 时传拷贝的做法,避免相互影响。
修改后的完整代码示例
apiCall: IApiCallHistory | undefined; @Output() selectedApiCallChange = new EventEmitter<SelectedApiCall>(); getApiCall(identifier: string) { const parametersKeyValuePair = new Array<KeyValuePair<string, string>>(); this.sapEtService.getApiCallHistoryById(identifier) .subscribe(apiCall => { this.apiCall = apiCall; for (let parameter of this.apiCall.apiCallWithParameters.apiCallParameters) { parametersKeyValuePair.push( new KeyValuePair<string, string>( parameter.identifier, parameter.value )); } // 用构造函数创建实例 + 数组浅拷贝 const selectedApiCall = new SelectedApiCall( identifier, [...parametersKeyValuePair] ); console.log('parametersKeyValuePair:::: ', parametersKeyValuePair); console.log('selectedApiCall.predefinedParameters:::: ', selectedApiCall.predefinedParameters); this.selectedApiCallChange.emit(selectedApiCall); // 原内部订阅的逻辑直接放在这里执行即可,不需要额外订阅 console.log('this.selectedApiCallChange in ApiCall History:::: ', selectedApiCall); }); }
内容的提问来源于stack exchange,提问作者Reza Gholizadeh
相关产品推荐
相关产品推荐

