Bootstrap联动下拉框二次选择后无法展开问题求助
问题描述
使用Bootstrap 5创建两个联动下拉框,期望第二个下拉框的选项随第一个的选中值动态更新。现有字典data,键对应第一个下拉框的选项,值为第二个下拉框的选项集合。通过fill_categorie生成包含选项的<ul>结构,替换第二个下拉框的原有<ul>实现更新。首次选择第一个下拉框时,第二个下拉框可正常展开并选择;但二次选择第一个下拉框后,第二个下拉框无法展开,尽管HTML代码已正确更新。
问题原因
- Bootstrap Dropdown实例绑定丢失:Bootstrap的Dropdown组件会在页面加载时为每个下拉框创建对应的JS实例,并绑定到原始DOM元素上。当通过
replaceChild替换第二个下拉框的<ul class="dropdown-menu">时,原有的绑定节点被移除,新生成的<ul>未被Bootstrap的Dropdown逻辑关联,导致点击按钮无法触发展开动作。 - 事件重复绑定:原
select_btn函数每次点击下拉按钮时,都会为当前选项绑定新的click事件,多次点击会导致同一个选项被绑定多个事件,引发逻辑异常。
解决方案及修复代码
核心修复点
- 保留第二个下拉框原始的
<ul>节点,仅清空并替换内部的<li>选项,避免Dropdown实例失效。 - 使用事件委托绑定选项点击事件,无需每次更新选项后重新绑定,同时避免重复绑定问题。
完整修复代码
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet"/> <div class="col-lg-4 col-md-4 col-sm-12"> <div> <h5>DropDown 1</h5> <div class="dropdown"> <button id="btnID" class="btn btn-secondary dropdown-toggle" type="button"data-bs-toggle="dropdown" aria-expanded="false"> DropDown1 </button> <ul class="dropdown-menu"> <li class="dropdown-item ">A</li> <li class="dropdown-item ">B</li> <li class="dropdown-item ">C</li> </ul> </div> <br><br> </div> <h5>DropDown 2</h5> <div class="dropdown"> <button id="btn2ID" class="btn btn-secondary dropdown-toggle" type="button"data-bs-toggle="dropdown" aria-expanded="false"> DropDown 2 </button> <ul class="dropdown-menu"> </ul> </div> </div> <script> let data = { "A": ["A1", "A2"], "B": ["B1", "B2", "B3"], "C": ["C1"] }; // 填充选项到指定的ul中,而非创建新ul function fill_categorie(ul, tableau) { // 清空原有内容 ul.innerHTML = ''; for (let item of tableau) { const li = document.createElement("li"); li.classList.add("dropdown-item"); li.textContent = item; ul.appendChild(li); } } // 事件委托处理所有下拉选项的点击 document.addEventListener('click', function(e) { if (e.target.classList.contains('dropdown-item')) { const dropdownItem = e.target; const selectedText = dropdownItem.textContent.trim(); // 获取对应的下拉按钮 const dropdownBtn = dropdownItem.closest('.dropdown').querySelector('.dropdown-toggle'); dropdownBtn.textContent = selectedText; // 如果是第一个下拉框的选择,更新第二个下拉框 if (dropdownBtn.id === "btnID") { updateListLabel(selectedText); } } }); function updateListLabel(selectedElem) { const ctg = data[selectedElem]; const btn_ctg = document.getElementById("btn2ID"); // 获取原始的ul节点,而非替换 const ul_ctg = btn_ctg.nextElementSibling; fill_categorie(ul_ctg, ctg); // 重置第二个下拉框的按钮文本 btn_ctg.textContent = "DropDown 2"; } </script>
代码说明
- 保留原始ul节点:
fill_categorie函数接收已有的<ul>元素,清空其内容后添加新选项,避免替换整个节点导致Dropdown实例失效。 - 事件委托:通过在
document上监听click事件,判断点击目标是否为.dropdown-item,无论选项是初始加载还是动态生成,都能触发点击逻辑,同时避免重复绑定事件。 - 简化逻辑:移除原代码中基于Promise的复杂事件绑定,改用更简洁的事件委托方式,提升代码可读性和稳定性。
内容的提问来源于stack exchange,提问作者problème0123
相关产品推荐
相关产品推荐

