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

如何在原生JS国家代码选择器中用addEventListener替代重复onclick

替换onclick为addEventListener实现国家代码选择器

问题说明

当前代码在每个<li>选项上都使用onclick="updateName(this)"触发选中逻辑,不仅代码冗余不美观,还会因频繁绑定事件影响性能,需要改用addEventListener结合事件委托的方式优化。

解决方案

利用事件委托机制,直接在父元素.options上绑定一次click事件,无需给每个<li>单独绑定,既简化代码又提升性能,具体修改如下:

  1. 移除生成<li>时的onclick属性
  2. 给.options元素添加click事件监听器,通过事件委托判断点击目标是否为<li>
  3. 确保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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:40:41