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

如何为自定义国家码下拉框的选中选项设置背景高亮

问题解决:国家码下拉选择器选中项无法高亮

问题描述

实现的国际化国家码下拉选择器功能正常,但用户选中选项后再次打开下拉列表,已选选项无法通过CSS高亮显示。

问题根源

  1. 重复事件绑定:handleDocumentClick函数内部重复给document添加点击监听器,导致下拉列表的显示/隐藏逻辑异常,影响选中项样式渲染。
  2. CSS优先级不足:.selected-country类的优先级与.cc-list-items相同,可能被其他样式(如hover)覆盖,导致高亮不生效。
  3. DOM结构错误:按钮内部使用<option>标签不符合HTML规范,可能引发浏览器解析异常。
  4. CSS拼写错误:.cc-data-list的border属性值拼写错误(soldi应为solid),虽不影响高亮,但需修正以保证样式完整性。

修复方案

1. 修复重复事件绑定

修改handleDocumentClick函数,移除内部重复添加的监听器,直接处理点击逻辑:

function handleDocumentClick(event) {
  if (!formRoot.contains(event.target)) {
    ccContainer.classList.remove("show-cc-list");
  }
}

2. 提高选中项CSS优先级

使用组合选择器提升选中项样式优先级,确保高亮生效,同时添加文字颜色增强对比度:

.cc-list-items.selected-country {
  cursor: pointer;
  background-color: rgb(73, 118, 241);
  color: white;
}

3. 修复按钮内的DOM元素

将createButtonHtml中的<option>标签替换为<span>,符合HTML规范:

function createButtonHtml(code, flag) {
  return `
    <div class="flag-icon flag-icon-${flag}"></div>
    <span class="cc-code" value="+${code}">+${code}</span>
  `;
}

4. 修正CSS拼写错误

修正.cc-data-list的border属性拼写:

.cc-data-list {
  /* 其他样式不变 */
  border: 1px solid darkgray;
}

完整修改后的代码

JavaScript

const countryData = [
  { name: "Afganistan", code: "93", flag: "afg" },
  { name: "Albania", code: "355", flag: "alb" },
  { name: "Algeria", code: "213", flag: "dza" },
  { name: "Canada", code: "1", flag: "can" },
  { name: "Cape Verde", code: "238", flag: "cpv" },
  { name: "Cayman Islands", code: "1-345", flag: "cym" },
  { name: "United States", code: "1", flag: "usa" },
  { name: "Uruguay", code: "598", flag: "ury" },
  { name: "Uzbekistan", code: "998", flag: "uzb" }
];

function registerForm(formRoot) {
  const ccButton = formRoot.querySelector(".cc-telcode");
  const ccContainer = formRoot.querySelector(".cc-container");
  const ccSearchInput = formRoot.querySelector(".cc-search-box");
  const ccList = formRoot.querySelector(".cc-data-list");
  let selectedCountry = ""; // 以code为标识保存选中项

  ccButton.addEventListener("click", handleButton);
  ccSearchInput.addEventListener("input", handleInput);
  ccList.addEventListener("click", handleListClick);
  document.addEventListener("click", handleDocumentClick);

  function handleDocumentClick(event) {
    if (!formRoot.contains(event.target)) {
      ccContainer.classList.remove("show-cc-list");
    }
  }

  function handleButton() {
    ccContainer.classList.toggle("show-cc-list");
    ccList.innerHTML = createListHtml(countryData);
  }

  function createListHtml(countryData) {
    return countryData.map((obj) => {
        const { name, code, flag } = obj;
        let isSelected = "";
        if (obj.code == selectedCountry) isSelected = "selected-country";
        return `
          <li class="cc-list-items ${isSelected}" data-name="${name}" data-code="${code}" data-flag="${flag}">
              <div class="flag-icon flag-icon-${flag}"></div>
              <div class="name">${name} (+${code})</div>
          </li>
        `;
      }).join("");
  }

  function handleInput(e) {
    const { value } = e.target;
    if (value) {
      const filtered = filterData(countryData, value);
      if (filtered.length) {
        ccList.innerHTML = createListHtml(filtered);
      } else {
        ccList.innerHTML = createNoDataHtml();
      }
    } else {
      ccList.innerHTML = createListHtml(countryData);
    }
  }

  function handleListClick(e) {
    const item = e.target.closest("li") || e.target;
    if (item.classList.contains("cc-list-items")) {
      const { code, flag } = item.dataset;
      selectedCountry = item.dataset.code;
      ccButton.innerHTML = createButtonHtml(code, flag);
      ccContainer.classList.remove("show-cc-list");
    }
  }
}

function filterData(countryData, value) {
  return countryData.filter((obj) => {
    return (
      obj.name.toLowerCase().startsWith(value.toLowerCase()) ||
      obj.code.toLowerCase().startsWith(value.toLowerCase())
    );
  });
}

function createButtonHtml(code, flag) {
  return `
    <div class="flag-icon flag-icon-${flag}"></div>
    <span class="cc-code" value="+${code}">+${code}</span>
  `;
}

function createNoDataHtml() {
  return '<li class="no-data-found">Sorry, No Data Found</li>';
}

const contactDiv = document.querySelector(".contact-frm-cc");
registerForm(contactDiv);

CSS

.cc-telcode {
  margin-bottom: 1em;
  display: flex;
  justify-content: center;
  width: 100%;
}

.cc-telcode span.cc-code,
.cc-list-items div.name {
  margin-left: 0.25em;
}
.cc-container {
  display: none;
  width: 300px;
  position: absolute;
}
.show-cc-list {
  display: block;
  z-index: +999;
}
.cc-data-list {
  max-height: 100px;
  list-style: none;
  margin: 1em 0 0 0;
  padding: 0;
  overflow-y: scroll;
  border: 1px solid darkgray;
}
.cc-list-items {
  display: flex;
  padding: 0.25em;
  border: 1px solid lightgray;
}
.cc-list-items:hover {
  cursor: pointer;
  background-color: lightyellow;
}

.cc-list-items.selected-country {
  cursor: pointer;
  background-color: rgb(73, 118, 241);
  color: white;
}

.contact-frm-cc,
.consult-frm-cc {
  width: 100px;
}

HTML

<link href="https://amitdutta.co.in/flag/css/flag-icon.css" rel="stylesheet"/>
<div class="contact-frm-cc">
  <button class="cc-telcode">Tel code</button>
  <section class="cc-container">
    <input type="text" class="cc-search-box" placeholder="Search for country" />
    <ul class="cc-data-list">
    </ul>
  </section>
</div>

效果说明

修改后,用户选中国家码选项后,再次打开下拉列表时,已选选项会通过蓝色背景搭配白色文字高亮显示,符合预期需求。

内容的提问来源于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 09:35:15