如何在网页在线测验项目中优雅复用JS代码,无需重复复制修改变量?
核心优化思路
你完全不需要给每个题目单独写HTML和绑定事件,只要做到「数据与逻辑分离」就能实现无限加题不用改逻辑代码:
- 把所有题目信息用统一的数组结构存储,新增题目只需要加数组项
- 用JS动态生成所有题目的HTML结构,不用手动写重复的questionBox
- 通用的判分逻辑复用,通过DOM节点关联找到对应题目数据判断正误
简化后的HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>DOM STUFF</title> <link rel="stylesheet" href="styles.css" /> </head> <body> <h1 id="counter-display">Total: <span id="score">0</span></h1> <!-- 所有题目动态渲染到这个容器里 --> <div id="questionContainer"></div> <script src="dom.js"></script> </body> </html>
高复用性JS代码
const counterDisplayElem = document.getElementById('score'); const questionContainer = document.getElementById('questionContainer'); // 总得分 let total = 0; // 所有题目配置,新增题目只需要在这里加对象即可 const questionList = [ { id: 1, title: "Q1: What is My favorite Food?", options: ["Chicken", "Pork", "Seafood", "Junkfood", "Vegetables"], correct: "Pork" }, { id: 2, title: "Q2: What is My favorite ETC?", options: ["Chicken", "Pork", "Seafood", "Junkfood", "Vegetables"], correct: "Seafood" }, { id: 3, title: "Q3: What is My favorite Sport?", options: ["Running", "Swimming", "Basketball", "Football", "Badminton"], correct: "Basketball" } ]; // 渲染所有题目 function renderQuestions() { questionList.forEach(q => { // 生成题目HTML const questionBox = document.createElement('div'); questionBox.className = 'questionBox'; questionBox.dataset.id = q.id; // 绑定题目id关联数据 // 选项HTML拼接 let optionsHtml = ''; q.options.forEach(opt => { optionsHtml += `<input type="radio" name="answer_${q.id}" value="${opt}" /> ${opt} `; }); questionBox.innerHTML = ` <p class="question">${q.title}</p> <p>${optionsHtml}</p> <p><button class="submitBtn">Submit</button></p> `; questionContainer.appendChild(questionBox); }); } // 绑定提交事件(用事件委托更高效,不用循环绑定每个按钮) questionContainer.addEventListener('click', (e) => { // 判断点击的是提交按钮 if (e.target.classList.contains('submitBtn')) { const currentBox = e.target.closest('.questionBox'); const questionId = parseInt(currentBox.dataset.id); const currentQuestion = questionList.find(q => q.id === questionId); const selectedOpt = currentBox.querySelector(`input[name="answer_${questionId}"]:checked`); // 未选提示 if (!selectedOpt) { alert("请选择答案"); return; } // 判分 if (selectedOpt.value === currentQuestion.correct) { total++; counterDisplayElem.innerText = total; e.target.style.display = 'none'; // 隐藏提交按钮 } else { alert("Incorrect"); currentBox.querySelector('.question').innerText += " Epic Fail"; } } }); // 初始化渲染 renderQuestions();
优化后优势
- 新增题目只需要在
questionList数组里加一个对象即可,不需要改任何逻辑代码和HTML结构 - 所有逻辑100%复用,没有重复代码
- 后续要修改题目样式、判分逻辑,只需要改一次公共代码即可生效所有题目
内容的提问来源于stack exchange,提问作者DozerDog
相关产品推荐
相关产品推荐

