如何在原生JS国家代码选择器中用addEventListener替代重复onclick
替换onclick为addEventListener实现国家代码选择器
问题说明
当前代码在每个<li>选项上都使用onclick="updateName(this)"触发选中逻辑,不仅代码冗余不美观,还会因频繁绑定事件影响性能,需要改用addEventListener结合事件委托的方式优化。
解决方案
利用事件委托机制,直接在父元素.options上绑定一次click事件,无需给每个<li>单独绑定,既简化代码又提升性能,具体修改如下:
- 移除生成
<li>时的onclick属性 - 给
.options元素添加click事件监听器,通过事件委托判断点击目标是否为<li> - 确保
updateName函数逻辑正常兼容
修改后的完整JS代码
const wrapper = document.querySelector(".wrapper"), selectBtn = wrapper.querySelector(".select-btn"), searchInp = wrapper.querySelector("input"), options = wrapper.querySelector(".options"); let countries = [ "<span class='flag-icon flag-icon-afg'></span> Afghanistan (+93)", "<span class='flag-icon flag-icon-bel'></span> Belgium (+32)", "<span class='flag-icon flag-icon-chn'></span> China (+86)", ]; function addCountry(selectedCountry) { options.innerHTML = ""; countries.forEach(country => { let isSelected = country == selectedCountry ? "selected" : ""; // 移除内联onclick属性 let li = `<li class="${isSelected}">${country}</li>`; options.insertAdjacentHTML("beforeend", li); }); } addCountry(); function updateName(selectedLi) { searchInp.value = ""; addCountry(selectedLi.innerHTML); wrapper.classList.remove("active"); const filterData = /(<span\b[^<>]*><\/span>\s*)\w+(?:\s+\w+)*\s*\((\+[\d-]+)\)/g; selectBtn.firstElementChild.innerHTML = selectedLi.innerHTML.replace(filterData, `$1$2`); } // 事件委托:父元素监听子元素点击 options.addEventListener("click", (e) => { const targetLi = e.target.closest("li"); if (targetLi) { updateName(targetLi); } }); searchInp.addEventListener("keyup", () => { let arr = []; let searchWord = searchInp.value.toLowerCase(); arr = countries.filter(data => { return data.toLowerCase().includes(searchWord); }).map(data => { let isSelected = data == selectBtn.firstElementChild.innerHTML ? "selected" : ""; // 移除内联onclick属性 return `<li class="${isSelected}">${data}</li>`; }).join(""); options.innerHTML = arr ? arr : `<p style="margin-top: 10px;">Oops! Country not found</p>`; }); selectBtn.addEventListener("click", () => wrapper.classList.toggle("active")); document.addEventListener('click', (event)=> { if (!wrapper.contains(event.target)) { wrapper.classList.remove("active"); }else{ wrapper.classList.add("active"); } });
核心优化说明
- 事件委托优势:仅在父元素绑定一次事件,即可处理所有动态生成的
<li>点击,避免频繁绑定/销毁事件的性能开销 - 代码简洁性:移除冗余内联属性,代码结构更清晰易维护
- 容错性:使用
closest("li")确保点击<li>内部子元素(如国旗图标)时,仍能正确触发选中逻辑
内容的提问来源于stack exchange,提问作者Gupa Dutta
相关产品推荐
相关产品推荐

