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

如何在select框添加多选项?仅用JavaScript实现带复选框的多选下拉

实现带复选框的多选下拉框(纯JavaScript)

原生的<select>标签本身并不支持带复选框的多选交互,所以我们需要通过自定义UI组件来实现这个需求,同时保持和原<select>元素的值同步,确保表单提交时数据能正常传递。下面是完整的实现方案:

核心思路

  • 隐藏原有的<select>元素,用自定义的下拉容器替代它的视觉展示
  • 创建包含复选框的选项列表,迁移原选项并添加新选项
  • 实现下拉菜单的展开/收起交互
  • 同步复选框的选中状态到原<select>,保证表单数据能正常提交

完整代码示例

<!-- 原有的select元素 -->
<select class="form-control" id="mySelect">
  <option value="0">--- Please Select ----</option>
  <option value="html">html</option>
</select>

<!-- JS会动态创建自定义下拉结构,这里先留空 -->
<div id="customSelectContainer"></div>

<style>
/* 自定义下拉的基础样式,匹配原生form-control风格 */
.custom-select-trigger {
  padding: 8px 12px;
  border: 1px solid #ced4da;
  border-radius: 4px;
  background-color: white;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 4px;
}

.custom-select-trigger::after {
  content: "▼";
  font-size: 12px;
  margin-left: 8px;
}

.custom-select-menu {
  position: absolute;
  border: 1px solid #ced4da;
  border-radius: 4px;
  background-color: white;
  max-height: 200px;
  overflow-y: auto;
  display: none;
  z-index: 100;
}

.custom-select-option {
  padding: 8px 12px;
  cursor: pointer;
  display: flex;
  align-items: center;
}

.custom-select-option:hover {
  background-color: #f8f9fa;
}

.custom-select-option input[type="checkbox"] {
  margin-right: 8px;
}

/* 隐藏原生select,只保留其数据提交功能 */
#mySelect {
  display: none;
}
</style>

<script>
document.addEventListener('DOMContentLoaded', function() {
  // 获取原生select元素
  const originalSelect = document.getElementById('mySelect');
  // 获取自定义下拉的容器
  const container = document.getElementById('customSelectContainer');
  
  // 1. 创建下拉触发按钮
  const triggerBtn = document.createElement('div');
  triggerBtn.className = 'custom-select-trigger';
  triggerBtn.textContent = '--- Please Select ----';
  
  // 2. 创建下拉菜单容器
  const menu = document.createElement('div');
  menu.className = 'custom-select-menu';
  
  // 3. 准备要新增的选项,你可以在这里添加更多条目
  const newOptions = [
    { value: 'css', text: 'css' },
    { value: 'javascript', text: 'javascript' },
    { value: 'react', text: 'react' }
  ];
  
  // 迁移原生select的现有选项到自定义菜单
  Array.from(originalSelect.options).forEach(option => {
    if (option.value !== '0') { // 跳过默认提示选项
      addCheckboxOption(option.value, option.textContent);
    }
  });
  
  // 添加新选项到自定义菜单
  newOptions.forEach(opt => {
    addCheckboxOption(opt.value, opt.text);
  });
  
  // 辅助函数:创建带复选框的选项条目
  function addCheckboxOption(value, text) {
    const optionDiv = document.createElement('div');
    optionDiv.className = 'custom-select-option';
    
    const checkbox = document.createElement('input');
    checkbox.type = 'checkbox';
    checkbox.value = value;
    
    const label = document.createElement('span');
    label.textContent = text;
    
    optionDiv.appendChild(checkbox);
    optionDiv.appendChild(label);
    
    // 复选框状态变化时,同步到原生select并更新按钮文本
    checkbox.addEventListener('change', function() {
      syncToOriginalSelect();
      updateTriggerDisplay();
    });
    
    menu.appendChild(optionDiv);
  }
  
  // 4. 实现下拉菜单的展开/收起
  triggerBtn.addEventListener('click', function() {
    menu.style.display = menu.style.display === 'block' ? 'none' : 'block';
  });
  
  // 点击页面其他区域关闭下拉菜单
  document.addEventListener('click', function(e) {
    if (!container.contains(e.target)) {
      menu.style.display = 'none';
    }
  });
  
  // 辅助函数:同步选中状态到原生select
  function syncToOriginalSelect() {
    // 清空原生select的所有选中状态
    Array.from(originalSelect.options).forEach(opt => opt.selected = false);
    
    const checkedBoxes = menu.querySelectorAll('input[type="checkbox"]:checked');
    
    // 如果没有选中任何选项,保留默认提示的选中状态
    if (checkedBoxes.length === 0) {
      originalSelect.options[0].selected = true;
      return;
    }
    
    // 开启原生select的多选模式
    originalSelect.multiple = true;
    
    // 为每个选中的选项同步到原生select(不存在则创建)
    checkedBoxes.forEach(box => {
      let existingOpt = originalSelect.querySelector(`option[value="${box.value}"]`);
      if (!existingOpt) {
        existingOpt = document.createElement('option');
        existingOpt.value = box.value;
        existingOpt.textContent = box.nextElementSibling.textContent;
        originalSelect.appendChild(existingOpt);
      }
      existingOpt.selected = true;
    });
  }
  
  // 辅助函数:更新触发按钮的显示文本
  function updateTriggerDisplay() {
    const checkedBoxes = menu.querySelectorAll('input[type="checkbox"]:checked');
    let displayText = '';
    
    if (checkedBoxes.length === 0) {
      displayText = '--- Please Select ----';
    } else if (checkedBoxes.length === 1) {
      displayText = checkedBoxes[0].nextElementSibling.textContent;
    } else {
      displayText = `${checkedBoxes.length} items selected`;
    }
    
    triggerBtn.textContent = displayText;
    triggerBtn.innerHTML += ' ▼';
  }
  
  // 将自定义组件添加到页面
  container.appendChild(triggerBtn);
  container.appendChild(menu);
});
</script>

代码说明

  • 样式部分:我们匹配了原生.form-control的视觉风格,同时隐藏了原生select,只保留它的数据提交功能。
  • 交互逻辑:
    • 页面加载完成后自动构建自定义下拉组件,迁移原有选项并添加新选项
    • 支持点击触发按钮展开/收起菜单,点击页面其他区域自动关闭
    • 复选框选中状态会实时同步到原生select,保证表单提交时能获取到所有选中的值
    • 触发按钮会根据选中数量动态显示文本,提升用户体验

你可以根据需求修改样式(比如颜色、间距),或者在newOptions数组里添加更多选项条目。

内容的提问来源于stack exchange,提问作者vinaykumar0459

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:55:05