Angular中EventEmitter在ngOnInit时未触发问题求助
问题分析与解决方案
核心问题:@Output 使用场景完全错误
你误解了@Output()的作用——它是子组件向父组件传递事件的工具,组件自身内部根本没法通过HTML模板绑定自己的@Output事件来触发方法。你想要获取组件内的按钮元素,完全不需要用EventEmitter,这是方向上的错误。另外你的第一个<button>标签存在未闭合的语法错误,这也可能导致DOM渲染异常,影响后续逻辑。
解决方案:直接获取元素的几种正确方式
方式1:在点击事件中直接传递元素
既然已经绑定了(click)事件,直接在点击时把元素传给对应方法即可,不需要额外的事件绑定:
修改后的TS代码:
/** Variable pointing to the icons */ private seatIconTarget!: HTMLElement | undefined; private eyeIconTarget!: HTMLElement | undefined; private stageIconTarget!: HTMLElement | undefined; // 保留原有点击逻辑,同时触发元素赋值 onIconClick(type: string, ev: MouseEvent) { // 你的原有点击逻辑... // 调用对应元素赋值方法 switch(type) { case 'seat': this.setSeatIcon(ev); break; case 'eye': this.setEyeIcon(ev); break; case 'stage': this.setStageIcon(ev); break; } } /** Set the icons target for dynamically modifying the style of the specific object*/ setSeatIcon(ev: MouseEvent) { console.log('setSeat'); this.seatIconTarget = ev.currentTarget as HTMLElement; } setEyeIcon(ev: MouseEvent) { console.log('setEye'); this.eyeIconTarget = ev.currentTarget as HTMLElement; } setStageIcon(ev: MouseEvent) { console.log('setStage'); this.stageIconTarget = ev.currentTarget as HTMLElement; }
修改后的HTML代码:
<div *ngIf="show === false" class="head"> <!-- Buttons --> <!-- 修复第一个button的闭合问题,移除错误的(setTarget)绑定 --> <button mat-icon-button class="icon" (click)="onIconClick('seat', $event)"> <mat-icon title="Add seats">event_seat</mat-icon> </button> <button mat-icon-button class="icon" (click)="onIconClick('eye', $event)"> <mat-icon title="Hide clicked cells">remove_red_eye</mat-icon> </button> <button mat-icon-button class="icon" (click)="onIconClick('stage', $event)"> <mat-icon svgIcon="stage" title="Add stage"></mat-icon> </button> </div>
方式2:使用ViewChild获取模板引用元素
如果不需要点击触发,想在组件初始化后直接获取元素,可以用ViewChild:
TS代码:
import { ViewChild, ElementRef, AfterViewInit } from '@angular/core'; // ... 其他组件代码 @ViewChild('seatBtn') seatBtn!: ElementRef<HTMLElement>; @ViewChild('eyeBtn') eyeBtn!: ElementRef<HTMLElement>; @ViewChild('stageBtn') stageBtn!: ElementRef<HTMLElement>; ngAfterViewInit(): void { // 视图初始化完成后才能获取到DOM元素 this.seatIconTarget = this.seatBtn.nativeElement; this.eyeIconTarget = this.eyeBtn.nativeElement; this.stageIconTarget = this.stageBtn.nativeElement; console.log('seat element:', this.seatIconTarget); }
HTML代码:
<div *ngIf="show === false" class="head"> <!-- 给每个按钮添加模板引用变量 --> <button #seatBtn mat-icon-button class="icon" (click)="onIconClick('seat', $event)"> <mat-icon title="Add seats">event_seat</mat-icon> </button> <button #eyeBtn mat-icon-button class="icon" (click)="onIconClick('eye', $event)"> <mat-icon title="Hide clicked cells">remove_red_eye</mat-icon> </button> <button #stageBtn mat-icon-button class="icon" (click)="onIconClick('stage', $event)"> <mat-icon svgIcon="stage" title="Add stage"></mat-icon> </button> </div>
关键注意点
- 不要用
@Output处理组件内部的元素获取逻辑,它的唯一职责是组件间通信。 - 使用
ViewChild时,必须在ngAfterViewInit钩子中获取元素——ngOnInit阶段视图还未渲染完成,元素不存在。 - 优先用
ev.currentTarget而非ev.target,因为target可能指向按钮内部的<mat-icon>元素,而currentTarget始终是绑定事件的按钮本身。
内容的提问来源于stack exchange,提问作者Presti
相关产品推荐
相关产品推荐

