You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 01:31:22