如何用原生JS实现无jQuery/Bootstrap依赖的多选下拉框
原生JavaScript实现多选下拉框

原生<select>标签自带的多选功能样式无法灵活定制,和参考图效果差异较大,我们可以通过隐藏原生select、生成自定义DOM结构的方式实现,全程不依赖任何第三方库,同时保留原生select的表单值同步能力。
完整实现代码
在原有HTML基础上补充如下CSS和JS代码即可:
<!-- 原有select代码,需补充multiple属性支持多选 --> <select name="city" id="mySelect" multiple> <option value="banglore">Banglore</option> <option value="bhubaneswar">Bhubaneswar</option> <option value="patna">Patna</option> <option value="indore">Indore</option> </select> <style> /* 自定义多选下拉基础样式 */ .custom-multiselect { position: relative; width: 220px; font-family: system-ui, sans-serif; } .multiselect-header { border: 1px solid #d0d0d0; padding: 8px 12px; border-radius: 4px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; background: #fff; min-height: 20px; font-size: 14px; } .multiselect-header::after { content: "▼"; font-size: 12px; color: #666; } .multiselect-options { position: absolute; top: 100%; left: 0; right: 0; border: 1px solid #d0d0d0; border-top: none; border-radius: 0 0 4px 4px; max-height: 220px; overflow-y: auto; background: #fff; z-index: 99; display: none; margin-top: 2px; box-shadow: 0 2px 6px rgba(0,0,0,0.1); } .multiselect-options.show { display: block; } .multiselect-option { padding: 8px 12px; cursor: pointer; display: flex; align-items: center; gap: 8px; font-size: 14px; } .multiselect-option:hover { background: #f5f5f5; } .multiselect-option.selected { background: #eef4ff; } .multiselect-option input { margin: 0; cursor: pointer; } </style> <script> // 多选下拉初始化方法 function initMultiSelect(selectEl) { // 隐藏原生select selectEl.style.display = 'none'; // 创建自定义下拉结构 const container = document.createElement('div'); container.className = 'custom-multiselect'; const header = document.createElement('div'); header.className = 'multiselect-header'; header.textContent = '请选择城市'; const optionsWrap = document.createElement('div'); optionsWrap.className = 'multiselect-options'; // 遍历原生option生成自定义选项 const originOptions = selectEl.querySelectorAll('option'); originOptions.forEach(option => { const optionItem = document.createElement('label'); optionItem.className = 'multiselect-option'; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.value = option.value; // 复选框状态同步到原生select checkbox.addEventListener('change', () => { option.selected = checkbox.checked; optionItem.classList.toggle('selected', checkbox.checked); updateHeaderText(); }); const optionText = document.createElement('span'); optionText.textContent = option.textContent; optionItem.append(checkbox, optionText); optionsWrap.append(optionItem); }); // 更新头部已选内容显示 function updateHeaderText() { const selectedTexts = Array.from(selectEl.selectedOptions).map(opt => opt.textContent); header.textContent = selectedTexts.length ? selectedTexts.join(', ') : '请选择城市'; } // 点击头部切换下拉展开/收起 header.addEventListener('click', (e) => { e.stopPropagation(); optionsWrap.classList.toggle('show'); }); // 点击外部区域自动收起下拉 document.addEventListener('click', () => { optionsWrap.classList.remove('show'); }); // 点击选项区域内部不触发收起 optionsWrap.addEventListener('click', (e) => { e.stopPropagation(); }); // 组装DOM插入到原生select位置 container.append(header, optionsWrap); selectEl.parentNode.insertBefore(container, selectEl); } // 页面加载完成后初始化目标下拉框 document.addEventListener('DOMContentLoaded', () => { const citySelect = document.getElementById('mySelect'); initMultiSelect(citySelect); }); </script>
实现说明
- 必须给原生select标签添加
multiple属性才能支持多选值存储,最终表单提交、JS通过原生select API获取选中值的逻辑完全不受影响,不需要额外适配 - 点击下拉头部可展开/收起选项列表,点击选项前的复选框即可切换选中状态,选中项会有高亮背景
- 所有选中项的文本会自动拼接显示在下拉头部,未选择时显示默认提示文字
- 点击下拉框外部区域会自动收起选项列表,交互符合常规表单组件使用习惯
内容的提问来源于stack exchange,提问作者chandanmee
相关产品推荐
相关产品推荐

