You need to enable JavaScript to run this app. Angular 9中如何处理动态生成ul li的mouseover与mouseout事件
优惠活动
大模型
产品
解决方案
定价
更多

Angular 9中如何处理动态生成ul li的mouseover与mouseout事件

问题根因

  1. DOM选择逻辑错误:你使用的el.nextElementSibling('span')是查找当前li同级的下一个span兄弟节点,但你的span是li的子元素,所以该方法返回null,操作样式自然失效。
  2. 生命周期时机错误:ngOnInit执行时组件模板尚未完成DOM渲染,如果你是通过*ngFor动态生成li元素,此时查询到的li集合大概率为空,事件没有成功绑定。
  3. 原生事件绑定存在隐患:直接调用addEventListener绑定事件,组件销毁时如果不手动解绑,会导致内存泄漏。

解决方案

方案1:纯CSS实现(最推荐,无JS逻辑)

只需要加两行样式即可实现效果,不需要修改TS和HTML结构,性能最优:

/* 默认隐藏span */
.nav-tabs .item span {
  display: none;
}
/* li hover时显示内部的span */
.nav-tabs .item:hover span {
  display: block;
}

方案2:Angular原生事件绑定(适配动态生成li场景)

符合Angular开发规范,不需要手动操作DOM,动态新增/删除li自动生效:

  1. 修改app.component.html:
<ul class="nav-tabs">
  <!-- 循环生成动态li,绑定hover事件记录当前hover的索引 -->
  <li class="item" *ngFor="let item of tabList; let i = index"
    (mouseover)="hoverIdx = i"
    (mouseout)="hoverIdx = null">
    <a>{{item.name}}</a>
    <!-- 只有当前项被hover时才显示span -->
    <span *ngIf="hoverIdx === i"> -On </span>
  </li>
</ul>
  1. 修改app.component.ts,新增两个变量即可:
export class AppComponent {
  // 你的动态tab数据,可通过接口赋值
  tabList = [{name: 'Test1'}, {name: 'Test2'}, {name: 'Test3'}]
  // 记录当前hover的tab索引
  hoverIdx: number | null = null
}

方案3:修正你的原生JS写法

如果需要保留手动操作DOM的逻辑,修改如下:

import { AfterViewInit, Component, ElementRef, OnDestroy } from '@angular/core';

@Component({
  // 你的原有组件配置
})
export class AppComponent implements AfterViewInit, OnDestroy {
  constructor(private elRef: ElementRef) {}

  // 换用ngAfterViewInit生命周期,此时DOM已经渲染完成
  ngAfterViewInit() {
    const liList = this.elRef.nativeElement.querySelectorAll('ul.nav-tabs li');
    liList.forEach(el => {
      el.addEventListener('mouseover', this.handleMouseOver);
      el.addEventListener('mouseout', this.handleMouseOut);
    });
  }

  private handleMouseOver(e: Event) {
    // 查找当前li内部的span元素
    const span = (e.currentTarget as HTMLElement).querySelector('span');
    if(span) span.style.display = 'block';
  }

  private handleMouseOut(e: Event) {
    const span = (e.currentTarget as HTMLElement).querySelector('span');
    if(span) span.style.display = 'none';
  }

  // 组件销毁时解绑事件,避免内存泄漏
  ngOnDestroy() {
    const liList = this.elRef.nativeElement.querySelectorAll('ul.nav-tabs li');
    liList.forEach(el => {
      el.removeEventListener('mouseover', this.handleMouseOver);
      el.removeEventListener('mouseout', this.handleMouseOut);
    });
  }
}

内容的提问来源于stack exchange,提问作者Sansara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 11:54:03