TypeScript中如何优雅地批量为多个元素添加/移除类?
优化类切换的TypeScript代码
我有一个需要添加或移除类的开关,在我的.ts文件中编写了如下代码:
export default class extends Controller { static targets = [ "InformationOne", "InformationTwo", "InformationThree", "InformationFour", "InformationSwitchOne", "InformationSwitchTwo" ]; private InformationOne: HTMLElement[]; private InformationTwo: HTMLElement[]; private InformationThree: HTMLElement[]; private InformationFour: HTMLElement[]; private InformationSwitchOne: HTMLInputElement; private InformationSwitchTwo: HTMLInputElement; switchInformation(): void { if (this.InformationSwitchOne.checked) { this.InformationOne.forEach((item) => { item.classList.remove("d-none"); }); this.InformationTwo.forEach((item) => { item.classList.add("d-none"); }); this.InformationThree.forEach((item) => { item.classList.add("d-none"); }); this.InformationFour.forEach((item) => { item.classList.add("d-none"); }); } else if (this.InformationSwitchTwo.checked) { this.InformationTwo.forEach((item) => { item.classList.remove("d-none"); }); this.InformationOne.forEach((item) => { item.classList.add("d-none"); }); this.InformationThree.forEach((item) => { item.classList.add("d-none"); }); this.InformationFour.forEach((item) => { item.classList.add("d-none"); }); } } }
现在的问题是,如何让以下代码更优雅?有没有办法一次性获取这三个元素并为它们执行classList.add操作,而非逐个处理?
this.InformationTwo.forEach((item) => { item.classList.add("d-none"); }); this.InformationThree.forEach((item) => { item.classList.add("d-none"); }); this.InformationFour.forEach((item) => { item.classList.add("d-none"); })
优化方案
1. 合并数组批量处理
直接把需要操作的数组合并成一个新数组,一次性遍历完成类添加操作:
[...this.InformationTwo, ...this.InformationThree, ...this.InformationFour] .forEach(item => item.classList.add("d-none"));
如果这类操作需要多次复用,可以在类里封装一个工具方法:
private addClassToGroups(groups: HTMLElement[][], className: string) { groups.flat().forEach(item => item.classList.add(className)); } // 调用方式 this.addClassToGroups([this.InformationTwo, this.InformationThree, this.InformationFour], "d-none");
2. 统一管理所有信息元素
把所有信息元素数组统一存入一个集合,切换时先批量隐藏所有元素,再单独显示目标元素,大幅减少重复代码:
export default class extends Controller { static targets = [ "InformationOne", "InformationTwo", "InformationThree", "InformationFour", "InformationSwitchOne", "InformationSwitchTwo" ]; private InformationOne: HTMLElement[]; private InformationTwo: HTMLElement[]; private InformationThree: HTMLElement[]; private InformationFour: HTMLElement[]; private InformationSwitchOne: HTMLInputElement; private InformationSwitchTwo: HTMLInputElement; private allInfoGroups: HTMLElement[][] = []; connect() { this.allInfoGroups = [ this.InformationOne, this.InformationTwo, this.InformationThree, this.InformationFour ]; } switchInformation(): void { // 批量隐藏所有元素 this.allInfoGroups.flat().forEach(item => item.classList.add("d-none")); // 根据开关状态显示对应元素 if (this.InformationSwitchOne.checked) { this.InformationOne.forEach(item => item.classList.remove("d-none")); } else if (this.InformationSwitchTwo.checked) { this.InformationTwo.forEach(item => item.classList.remove("d-none")); } } }
后续新增信息元素时,只需要把对应的数组加入allInfoGroups即可,无需修改多处逻辑,扩展性更强。
3. 用CSS类切换实现(更简洁的思路)
如果DOM结构允许,把显示逻辑交给CSS,通过切换父容器的类来控制子元素显示,彻底避免JS批量操作:
/* 基础样式:隐藏所有信息项 */ .info-container .info-item { display: none; } /* 选中开关一时显示对应项 */ .info-container.show-info-one .info-item.one { display: block; } /* 选中开关二时显示对应项 */ .info-container.show-info-two .info-item.two { display: block; }
对应的JS代码简化为:
switchInformation(): void { const container = document.querySelector('.info-container'); container?.classList.remove('show-info-one', 'show-info-two'); if (this.InformationSwitchOne.checked) { container?.classList.add('show-info-one'); } else if (this.InformationSwitchTwo.checked) { container?.classList.add('show-info-two'); } }
这种方式符合关注点分离原则,把样式控制交还给CSS,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者mikolaj
相关产品推荐
相关产品推荐

