如何合并带事件监听器的多个函数?优化单选框交互代码
问题描述
尝试精简代码时遇到瓶颈:项目中点击按钮会显示10个radio输入框,选中某一选项后,所有单选框隐藏,且选中项的图片设为按钮背景。
目前通过重复的点击事件实现(示例代码):
optionOne.addEventListener("click", function() { showButton.style.backgroundImage = `url("${optionOneImage}")`; showButton.innerHTML = ""; optionsGrid.style.display = "none"; for (let i = 0; i < optionRadios.length; i++) { optionRadios[i].classList.replace("active", "hide"); } });
但由于选项数量多(后续可能到40+),希望代码更简洁,询问能否通过switch或其他方式统一处理逻辑。
优化方案
不需要switch语句,事件委托是更高效的方案,只需要绑定一次事件就能处理所有选项的点击,完全避免重复代码:
1. 移除冗余代码
删掉所有单个选项(optionOne、optionTwo等)的变量声明,以及对应的重复点击事件绑定代码。
2. 用事件委托处理所有选项点击
直接给optionsGrid绑定点击事件,通过事件对象定位目标元素:
optionsGrid.addEventListener('click', function(e) { // 找到点击的radio元素 const radio = e.target.closest('input[type="radio"]'); if (!radio) return; // 非radio点击直接退出 // 获取对应图片 const img = radio.parentElement.querySelector('img'); if (!img) return; // 设置按钮背景 showButton.style.backgroundImage = `url("${img.src}")`; showButton.innerHTML = ''; // 隐藏选项面板和所有单选框容器 optionsGrid.style.display = 'none'; Array.from(optionRadios).forEach(radioEl => { radioEl.classList.replace('active', 'hide'); }); });
3. 简化选项显示/隐藏逻辑
原showOptions函数的判断逻辑可以简化,无需遍历收集class,直接检查第一个单选框的状态:
function showOptions() { const firstRadio = optionRadios[0]; const isHidden = firstRadio.classList.contains('hide'); if (isHidden) { optionsGrid.style.animation = "open-animation 100ms linear 1"; optionsGrid.style.display = "grid"; Array.from(optionRadios).forEach(el => el.classList.replace('hide', 'active')); } else { optionsGrid.style.display = "none"; Array.from(optionRadios).forEach(el => el.classList.replace('active', 'hide')); } }
完整优化后的JavaScript代码
const showButton = document.getElementById("option-button"); const optionsGrid = document.getElementById("option-grid"); const optionRadios = document.getElementsByClassName("option-radio"); showButton.addEventListener("click", showOptions); function showOptions() { const firstRadio = optionRadios[0]; const isHidden = firstRadio.classList.contains('hide'); if (isHidden) { optionsGrid.style.animation = "open-animation 100ms linear 1"; optionsGrid.style.display = "grid"; Array.from(optionRadios).forEach(el => el.classList.replace('hide', 'active')); } else { optionsGrid.style.display = "none"; Array.from(optionRadios).forEach(el => el.classList.replace('active', 'hide')); } } optionsGrid.addEventListener('click', function(e) { const radio = e.target.closest('input[type="radio"]'); if (!radio) return; const img = radio.parentElement.querySelector('img'); if (!img) return; showButton.style.backgroundImage = `url("${img.src}")`; showButton.innerHTML = ''; optionsGrid.style.display = 'none'; Array.from(optionRadios).forEach(el => el.classList.replace('active', 'hide')); });
优化亮点
- 事件委托:父容器监听点击,自动识别目标选项,新增选项无需修改JS代码
- 简化遍历:用
Array.from将HTMLCollection转为数组,通过forEach替代传统for循环,代码更简洁 - 减少冗余:移除逐个声明选项和图片变量的代码,大幅缩减代码量
内容的提问来源于stack exchange,提问作者PsychedelicSeal
相关产品推荐
相关产品推荐

