多类名select下拉框change事件失效,点击value=0选项弹出文本框如何实现
解决方案
原有代码核心问题
querySelectorAll返回节点集合,无法直接读取.value属性,选中值获取逻辑错误- 循环绑定事件存在闭包陷阱,事件触发时
i为循环结束的最终值,无法匹配对应下拉框和文本框 - 重复绑定事件:每次
select触发change时都会重新绑定click和全局点击事件,导致逻辑混乱 - CSS中
.line-form .description.show选择器匹配失败,HTML无.line-form类,文本框显示逻辑失效 - 点击外部关闭的判断逻辑错误,未排除点击当前激活下拉框的场景,直接对节点集合调用
remove方法会报错
修正后完整代码
HTML
移除行内onchange事件,其余结构保留即可:
<div> <label for="example1">example1</label> <select class="selectBox" name="whois" id="example1" required> <option value="1" >No</option> <optgroup label="Yes"> <option value="0">Explain more for yes</option> </optgroup> </select> <textarea class="description" name="example1" cols="50" rows="3"></textarea> </div> <div> <label for="example2">example2</label> <select class="selectBox" name="whois" id="example2" required> <option value="1" >No</option> <optgroup label="Yes"> <option value="0">Explain more for yes</option> </optgroup> </select> <textarea class="description" name="example2" cols="50" rows="3"></textarea> </div> <div> <label for="example3">example3</label> <select class="selectBox" name="whois" id="example3" required> <option value="1" >No</option> <optgroup label="Yes"> <option value="0">Explain more for yes</option> </optgroup> </select> <textarea class="description" name="example3" cols="50" rows="3"></textarea> </div>
CSS
修正选择器匹配问题,添加父容器相对定位保证文本框位置正确:
/* 给下拉框父容器加相对定位,让文本框对应到所属下拉框下方 */ div:has(> .selectBox) { position: relative; margin-bottom: 70px; } select{ width: 70%; border:1px solid rgba(112, 112, 112, .5); padding: 15px; border-radius: 10px; outline: none; box-sizing: border-box; } select.active{ background: yellow; color: white; } .description{ border: 2px solid red; background-color: #e6eef7; border-radius: 10px; outline: none; position: absolute; left: 13.75%; top: calc(100% + 5px); z-index: 1; display: none; } /* 移除无效的.line-form前缀 */ .description.show { display: block; }
JS
重构事件绑定逻辑,满足全部需求:
document.addEventListener('DOMContentLoaded', function() { const selectBoxes = document.querySelectorAll('.selectBox'); const descriptions = document.querySelectorAll('.description'); // 绑定所有下拉框的change事件 selectBoxes.forEach((select, index) => { select.addEventListener('change', function() { // 切换下拉框时先关闭所有已打开的文本框,满足需求3 descriptions.forEach(des => des.classList.remove('show')); selectBoxes.forEach(sel => sel.classList.remove('active')); // 选中值为0时打开对应文本框,满足需求1 if (this.value === '0') { this.classList.add('active'); descriptions[index].classList.add('show'); } }); }); // 全局点击事件,点击非文本框区域关闭,满足需求2 document.addEventListener('click', function(e) { const activeDes = document.querySelector('.description.show'); const activeSelect = document.querySelector('.selectBox.active'); if (!activeDes) return; // 点击目标不是激活的文本框/下拉框时关闭 if (e.target !== activeDes && e.target !== activeSelect) { activeDes.classList.remove('show'); activeSelect.classList.remove('active'); } }); });
内容的提问来源于stack exchange,提问作者h.m.p.frontendDeveloper
相关产品推荐
相关产品推荐

