实现单选框互斥禁用:同题最符合/最不符合选项不可重复选
解决方案:实现同一题目中「最符合/最不符合」选项互斥
你的核心需求是确保同一题目下,「最符合」(Xm)和「最不符合」(Xs)不能选中相同选项,且切换选择后能自动恢复之前禁用的选项。原代码的问题在于字符串处理逻辑无效、全局变量无法区分不同题目,导致切换后状态混乱。下面是更简洁且健壮的实现方案:
问题分析
原代码的关键缺陷:
- JavaScript 字符串是不可变的,
radioSet.replace(...)不会修改原变量,必须将结果重新赋值才会生效; - 全局的
radioArray无法独立管理24道题的状态,导致切换选项后残留错误的禁用状态; - 逻辑仅处理首次选择,未覆盖「更换选项后恢复之前禁用项」的场景。
优化实现方案
第一步:简化HTML结构(移除冗余的onclick)
所有单选框无需单独绑定onclick,通过事件委托统一处理:
<!-- 示例前2题,其余22题保持相同结构即可 --> <div class="dt"> <div class="dtb"> <div class="dtr"> <div class="one">1</div> <div class="two">a</div> <div class="three"><input name="1m" type="radio" value="a" required /></div> <div class="four"><input name="1s" type="radio" value="a" required /></div> <div class="five">Aardig, vriendelijk</div> </div> <div class="dtr"> <div class="one"> </div> <div class="two">b</div> <div class="three"><input name="1m" type="radio" value="b" required /></div> <div class="four"><input name="1s" type="radio" value="b" required /></div> <div class="five">Overtuigend, overredend</div> </div> <div class="dtr"> <div class="one"> </div> <div class="two">c</div> <div class="three"><input name="1m" type="radio" value="c" required /></div> <div class="four"><input name="1s" type="radio" value="c" required /></div> <div class="five">Terughoudend, bescheiden, gereserveerd</div> </div> <div class="dtr"> <div class="one"> </div> <div class="two">d</div> <div class="three"><input name="1m" type="radio" value="d" required /></div> <div class="four"><input name="1s" type="radio" value="d" required /></div> <div class="five">Origineel, inventief, individualistisch</div> </div> </div> </div> <div class="dt"> <div class="dtb"> <div class="dtr"> <div class="one">2</div> <div class="two">a</div> <div class="three"><input name="2m" type="radio" value="a" required /></div> <div class="four"><input name="2s" type="radio" value="a" required /></div> <div class="five">Charmant, attractief, trekt anderen aan</div> </div> <div class="dtr"> <div class="one"> </div> <div class="two">b</div> <div class="three"><input name="2m" type="radio" value="b" required /></div> <div class="four"><input name="2s" type="radio" value="b" required /></div> <div class="five">Coöperatief, aangenaam</div> </div> <div class="dtr"> <div class="one"> </div> <div class="two">c</div> <div class="three"><input name="2m" type="radio" value="c" required /></div> <div class="four"><input name="2s" type="radio" value="c" required /></div> <div class="five">Koppig, onbuigzaam</div> </div> <div class="dtr"> <div class="one"> </div> <div class="two">d</div> <div class="three"><input name="2m" type="radio" value="d" required /></div> <div class="four"><input name="2s" type="radio" value="d" required /></div> <div class="five">Lief, innemend</div> </div> </div> </div>
第二步:JavaScript 事件委托实现互斥逻辑
利用事件委托一次性处理所有单选框的状态,无需为24题重复写代码:
// 给整个文档绑定事件委托,处理所有单选框的change事件 document.addEventListener('change', function(e) { const targetRadio = e.target; // 仅处理name以m/s结尾的单选框(匹配题目规则) if (targetRadio.type !== 'radio' || !/[ms]$/.test(targetRadio.name)) return; // 提取当前题目的编号和类型(m=最符合,s=最不符合) const questionId = targetRadio.name.slice(0, -1); const oppositeType = targetRadio.name.endsWith('m') ? 's' : 'm'; const oppositeGroupName = `${questionId}${oppositeType}`; // 获取对应题目的另一组单选框 const oppositeRadios = document.getElementsByName(oppositeGroupName); // 先恢复另一组所有选项的可用状态(避免残留禁用) oppositeRadios.forEach(radio => radio.disabled = false); // 如果当前单选框被选中,禁用另一组中相同value的选项 if (targetRadio.checked) { const sameValueRadio = Array.from(oppositeRadios).find(r => r.value === targetRadio.value); if (sameValueRadio) { sameValueRadio.disabled = true; // 若被禁用的选项之前是选中状态,自动取消选中(避免提交无效数据) if (sameValueRadio.checked) sameValueRadio.checked = false; } } });
方案优势
- 高效简洁:事件委托只需绑定一次,自动适配所有24道题,无需重复编写代码;
- 独立状态管理:通过
name属性提取题目编号,确保每道题的「最符合/最不符合」组独立运行,互不干扰; - 边界处理完善:切换选项时自动恢复之前禁用的选项,同时处理「被禁用选项已选中」的异常情况;
- 可扩展性强:后续新增题目只需保持相同的
Xm/Xs命名规则,无需修改JavaScript代码。
内容的提问来源于stack exchange,提问作者Ruben
相关产品推荐
相关产品推荐

