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

Angular 2中如何为当前点击的li添加类而非同级元素

问题:仅为点击的<li>元素添加active类,而非所有同级元素

我有如下DOM结构:

<div>
  <ul>
    <li>
      <ul>
        <li>Option 1</li>
        <li>Option 2</li>
        <li>Option 3</li>
      </ul>
    </li>
    <li>
      <ul>
        <li>Option 1</li>
        <li>Option 2</li>
        <li>Option 3</li>
      </ul>
    </li>
    <li>
      <ul>
        <li>Option 1</li>
        <li>Option 2</li>
        <li>Option 3</li>
      </ul>
    </li>
  </ul>
</div>

我需要为点击的<li>元素添加active类,而非其同级元素。目前我使用以下代码:

public select(item) { 
  this.selectedLi = item; 
} 
public isActive(item) { 
  return this.selectedLi === item; 
}

但这段代码会为所有<li>添加类,而非仅当前点击的元素。请问有什么解决办法?


解决方案

这个问题的核心是你大概率在模板层把所有<li>绑定到了同一个判断逻辑,但没有给每个<li>分配唯一的识别依据——毕竟你的子<li>内容都是重复的(比如多个Option 1),如果传递的是文本内容,相同文本的元素都会被判定为选中。下面是几种实用的解决思路:

1. 用唯一标识绑定数据(推荐,适合Angular等框架场景)

从代码的public关键字推测你在用Angular,最稳妥的方式是给每个选项添加唯一ID,通过数据绑定来区分元素:

组件内代码

// 定义带唯一标识的选项数据
private baseOptions = [
  { id: 1, name: 'Option 1' },
  { id: 2, name: 'Option 2' },
  { id: 3, name: 'Option 3' },
];

// 外层分组的选项,每个分组的选项ID不重复
groupedOptions = [
  { groupId: 'group1', options: [...this.baseOptions] },
  { groupId: 'group2', options: this.baseOptions.map(opt => ({...opt, id: opt.id + 3})) },
  { groupId: 'group3', options: this.baseOptions.map(opt => ({...opt, id: opt.id + 6})) },
];

public selectedLiId: number | null = null;

public select(item: {id: number, name: string}) { 
  this.selectedLiId = item.id; 
} 

public isActive(item: {id: number, name: string}) { 
  return this.selectedLiId === item.id; 
}

模板代码

<div>
  <ul>
    <li *ngFor="let group of groupedOptions">
      <ul>
        <li 
          *ngFor="let opt of group.options"
          (click)="select(opt)"
          [class.active]="isActive(opt)"
        >
          {{ opt.name }}
        </li>
      </ul>
    </li>
  </ul>
</div>

2. 直接操作DOM元素引用

如果不想用数据绑定,也可以直接传递当前<li>的DOM引用,通过元素实例对比来判断:

模板代码

<div>
  <ul>
    <li>
      <ul>
        <li (click)="select($event.currentTarget)" [class.active]="isActive($event.currentTarget)">Option 1</li>
        <li (click)="select($event.currentTarget)" [class.active]="isActive($event.currentTarget)">Option 2</li>
        <li (click)="select($event.currentTarget)" [class.active]="isActive($event.currentTarget)">Option 3</li>
      </ul>
    </li>
    <!-- 其他分组同理 -->
  </ul>
</div>

组件内代码

public selectedLi: HTMLLIElement | null = null;

public select(element: HTMLLIElement) { 
  // 先移除之前选中元素的active类
  if (this.selectedLi) {
    this.selectedLi.classList.remove('active');
  }
  // 标记当前元素并添加类
  this.selectedLi = element;
  this.selectedLi.classList.add('active');
} 

public isActive(element: HTMLLIElement) { 
  return this.selectedLi === element; 
}

注意:要用$event.currentTarget而非target,避免点击<li>内部子元素时获取到错误的DOM节点。

3. 支持分组独立选中(可选)

如果需要每个外层<li>下的子<li>可以各自选中一个,就用对象存储每个分组的选中状态:

组件内代码

public selectedItems: { [groupId: string]: number } = {};

public select(groupId: string, itemId: number) { 
  this.selectedItems[groupId] = itemId; 
} 

public isActive(groupId: string, itemId: number) { 
  return this.selectedItems[groupId] === itemId; 
}

模板代码

<div>
  <ul>
    <li *ngFor="let group of groupedOptions">
      <ul>
        <li 
          *ngFor="let opt of group.options"
          (click)="select(group.groupId, opt.id)"
          [class.active]="isActive(group.groupId, opt.id)"
        >
          {{ opt.name }}
        </li>
      </ul>
    </li>
  </ul>
</div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:09:06