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
相关产品推荐
相关产品推荐

