You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:44:51