JavaScript动态变量优化多选题考试答题数据获取方案求助
动态绑定多选题选中逻辑的优化方案
问题背景
我是JavaScript初学者,正在开发一个多选题考试项目,需要获取每道题选中答案的响应数据。手动编写代码可以实现该功能,但由于题目数量可能超过50道,希望通过动态变量优化代码以提升效率。
现有手动实现代码
var i; for (i = 1; i <= <?= session()->get('participant')['jml_soal'] ?>; i++) { window['radio' + i] = document.querySelectorAll("input[name='optionTrue" + i + "']"); window['rubahtombol' + i] = document.getElementById("buton" + i); } let findSe = () => { let selected = document.querySelector("input[name='optionTrue1']:checked").value; var soalId = document.getElementById("idSoal1").value; var opsiPilih = document.getElementById("jawaban" + selected).textContent document.getElementById("pilihan1").textContent = ". " + opsiPilih; rubahtombol1.classList.remove("btn-secondary"); rubahtombol1.classList.add("btn-primary") } let findSe1 = () => { let selected = document.querySelector("input[name='optionTrue2']:checked").value; var soalId = document.getElementById("idSoal2").value; var opsiPilih = document.getElementById("jawaban" + selected).textContent document.getElementById("pilihan2").textContent = ". " + opsiPilih; rubahtombol2.classList.remove("btn-secondary"); rubahtombol2.classList.add("btn-primary") } radio1.forEach(radioBtn => { radioBtn.addEventListener("change", findSe); }); radio2.forEach(radioBtn1 => { radioBtn1.addEventListener("change", findSe1); }); findSe(); findSe1();
尝试的循环实现(无法正常运行)
var i; for (i = 1; i <= <?= session()->get('participant')['jml_soal'] ?>; i++) { window['radio' + i] = document.querySelectorAll("input[name='optionTrue" + i + "']"); window['rubahtombol' + i] = document.getElementById("buton" + i); window['findSe' + i] = () => { let selected = document.querySelector("input[name='optionTrue1']:checked").value; var soalId = document.getElementById("idSoal1").value; console.log(selected); var opsiPilih = document.getElementById("jawaban" + selected).textContent console.log("aku pilih:" + opsiPilih); console.log("id saol:" + soalId); document.getElementById("pilihan1").textContent = ". " + opsiPilih; window['rubahtombol'+i.classList.remove("btn-secondary")]; window['rubahtombol'+i.classList.add("btn-primary")]; } } radio1.forEach(radioBtn => { radioBtn.addEventListener("change", findSe1); }); radio2.forEach(radioBtn1 => { radioBtn1.addEventListener("change", findSe2); }); findSe1(); findSe2();
需求:通过单一循环完成所有题目的逻辑绑定。
解决方案
你的循环实现存在几个核心问题:
- 箭头函数中引用的
i是闭包共享变量,循环结束后所有函数都会使用循环的最终值 - 函数内硬编码了
optionTrue1、idSoal1等固定ID,没有动态匹配当前题目序号 - 按钮类名操作语法错误,
window['rubahtombol'+i.classList.remove(...)]写法完全错误,需先获取元素再操作类名
以下是修正后的单一循环实现:
// 获取题目总数 const totalQuestions = <?= session()->get('participant')['jml_soal'] ?>; for (let i = 1; i <= totalQuestions; i++) { // 预获取当前题目的DOM元素,减少重复查询开销 const radioButtons = document.querySelectorAll(`input[name='optionTrue${i}']`); const submitButton = document.getElementById(`buton${i}`); const displaySelection = document.getElementById(`pilihan${i}`); // 定义当前题目的选中处理函数 const handleAnswerSelection = () => { // 获取当前选中的单选框,处理未选中的情况避免报错 const selectedRadio = document.querySelector(`input[name='optionTrue${i}']:checked`); if (!selectedRadio) return; const selectedValue = selectedRadio.value; const questionId = document.getElementById(`idSoal${i}`).value; const selectedOptionText = document.getElementById(`jawaban${selectedValue}`).textContent; // 更新选中答案的显示 displaySelection.textContent = `. ${selectedOptionText}`; // 更新按钮样式 submitButton.classList.remove("btn-secondary"); submitButton.classList.add("btn-primary"); // 如需收集所有题目答案,可在此将数据存入数组/对象 // 示例:const answers = {}; answers[questionId] = selectedValue; }; // 给当前题目的所有单选框绑定change事件 radioButtons.forEach(radio => { radio.addEventListener("change", handleAnswerSelection); }); // 初始化执行一次,显示默认选中的选项(如果有) handleAnswerSelection(); }
关键优化点
- 使用
let i声明循环变量,确保每次迭代的i都是独立值,解决闭包引用问题 - 用模板字符串替代字符串拼接,让选择器代码更易读、更不易出错
- 提前获取需要复用的DOM元素,减少重复调用
document.getElementById/querySelector的性能损耗 - 增加未选中状态的判断,避免因无选中项导致的代码报错
- 不再将变量挂载到
window全局对象,减少全局命名空间污染 - 函数命名更具语义化,提升代码可读性
此代码通过一个循环即可完成所有题目的事件绑定和初始化逻辑,无论题目数量多少都能自动适配。
内容的提问来源于stack exchange,提问作者Bayu Pratama
相关产品推荐
相关产品推荐

