Angular中@Output装饰器失效:父组件方法未触发求助
Angular EventEmitter 事件未触发问题排查与修复
核心问题分析
1. 递归子组件未传递事件
你的子组件是递归渲染的(内层 <app-tree-monitoreo> 未绑定 (datos) 和 (id) 事件),当点击内层的「Bus 1/Bus 2」复选框时,事件由内层子组件发出,但内层组件未与根父组件(MonitoreoComponent)建立事件绑定,导致父组件无法接收事件。
2. 复选框状态逻辑错误
子组件中 checkboxPreviousState 是每个组件实例单独维护的状态,点击不同复选框时会出现状态混乱;且代码末尾有冗余语句:this.checkboxPreviousState;,无实际作用。此外,依赖自定义状态判断复选框状态,不如直接使用事件对象的 checked 属性可靠。
3. Output 命名冲突风险
@Output() id = new EventEmitter<number>() 中,id 是 HTML 原生属性名,可能引发命名冲突,建议使用语义化名称。
分步修复代码
1. 修复子组件模板(tree-monitoreo.component.html)
让递归子组件传递事件,实现事件向上冒泡:
<div class="expandible" [style.margin-left.px]="(item.level === 2 ? 14 : item.level === 3 ? 43 : 0)"> <span *ngIf="item.children" (click)="toggleExpand()">[{{ item.expanded ? '-' : '+' }}]</span> <!-- 传递事件对象,用于获取复选框状态 --> <input type="checkbox" (change)="ActivarCheckBox($event, item.name)"> {{ item.name }} </div> <div *ngIf="item.expanded && item.children"> <app-tree-monitoreo *ngFor="let child of item.children" [item]="child" <!-- 内层组件事件向上传递 --> (datos)="datos.emit($event)" (removeMarkerId)="removeMarkerId.emit($event)"> </app-tree-monitoreo> </div>
2. 修复子组件逻辑(tree-monitoreo.component.ts)
- 替换冲突的 Output 名称
- 改用事件对象获取复选框状态,简化逻辑
export class TreeMonitoreoComponent { @Output() datos: EventEmitter<any[]> = new EventEmitter<any[]>(); // 替换原id,避免命名冲突 @Output() removeMarkerId = new EventEmitter<number>(); @Input() item:any; busData = [ { name: "Bus 1", longitude: -79.025062, latitude: -8.134483, nId: 1, msg: "msg1"}, { name: "Bus 2", longitude: -79.039958, latitude: -8.111403, nId: 2, msg: "msg2"}, ] toggleExpand() { console.log("entro a toggle expand"); this.item.expanded = !this.item.expanded; } // 接收事件对象,直接获取复选框状态 ActivarCheckBox(event: Event, value: any) { console.log("in Activarcheckbox"); const isChecked = (event.target as HTMLInputElement).checked; // 简化数据查找逻辑 const targetBus = this.busData.find(bus => bus.name === value); if (!targetBus) return; if (isChecked) { this.datos.emit([targetBus.latitude, targetBus.longitude, targetBus.nId, targetBus.msg]); } else { this.removeMarkerId.emit(targetBus.nId); } } }
3. 修复父组件模板(monitoreo.component.html)
更新绑定的 Output 名称,匹配子组件修改后的名称:
<body> <div class="menu"> <app-menu></app-menu> </div> <div class="nav-monitoring"> <div class="resizable"> <div class="tree-container"> <app-tree-monitoreo class="tree-item" *ngFor="let item of treeData" (datos)="actualizarMapa($event)" <!-- 更新为新的Output名称 --> (removeMarkerId)="removerMarca($event)" [item]="item"> </app-tree-monitoreo> </div> </div> <div class="adjacent" id="map"></div> </div> </body>
额外验证点
确认 busData 中的 name 值与 treeData 中「Bus 1/Bus 2」的名称完全一致(无大小写、空格差异),否则无法匹配到目标数据。
内容的提问来源于stack exchange,提问作者Luis Llontop
相关产品推荐
相关产品推荐

