JavaScript表单无法保存答案问题排查求助
修复测验表单的答案保存与状态恢复问题
需求与问题
需求:
- 保存用户答题结果,点击「返回」按钮时高亮显示之前选择的选项
- 根据用户答对的题目数量跳转至对应页面
当前存在的问题:
- 答案完全无法保存,
console.log仅能记录第一题的答案 - 点击「返回」按钮后,所有题目选中状态一致
问题根源分析
- 单选框元素未动态更新:表单里的单选框始终使用
q1作为name属性,切换到后续题目时,没有生成对应q2、q3的单选框,导致所有题目共用同一组单选框,状态混乱。 - CSS选择器语法错误:恢复选中状态时使用了错误的选择器
input[name="qX"]:[value="Y"],多了一个不必要的冒号,导致无法正确定位单选框。 - 答案存储与读取逻辑不匹配:切换题目时没有同步更新表单内的单选框结构,导致读取之前保存的答案时无法找到对应元素。
修复后的完整代码
<style> /* CSS Styles for the quiz - Customize as needed */ /* Styling for the quiz container */ #quizContainer { padding: 20px; border-radius: 10px; max-width: 600px; /* Set a maximum width */ margin: 0 auto; /* Center the container */ } /* Styling for the title and subtitle */ #titleContainer { background-color: #dfedef; /* Background color for title and subtitle */ padding: 5px 20px; /* Added top and bottom padding */ border-radius: 10px; margin-bottom: 20px; text-align: center; /* Center align the text */ } /* Styling for the question number and question */ #questionContainer { background-color: #fcfaf7; /* Background color */ padding: 10px; /* Added padding */ border-radius: 10px; /* Added border radius */ margin-bottom: 20px; /* Added margin */ } /* Styling for the title */ h1 { font-size: 1.2em; /* Half the original size */ margin-top: 0; margin-bottom: 0; color: #2d536a; /* Changed title color */ } #age { font-size: 0.8em; /* 3/4 of the current size */ font-weight: bold; color: #b95966; /* Color for "15-18 meses" */ margin-top: 0; } /* Styling for Yes/No buttons */ input[type="radio"] { display: none; /* Hide default radio buttons */ } label.btn { display: inline-block; margin: 5px; padding: 6px 16px; /* Adjusted padding */ border: 1px solid #2d536a; /* Changed outline color */ border-radius: 5px; /* Adding border radius */ cursor: pointer; transition: background-color 0.3s ease, color 0.3s ease; } input[type="radio"]:checked+label.btn { background-color: #63a3ad; /* Changed background color when selected */ color: white; /* Changed text color */ } /* Styling for Previous/Next buttons */ #prevBtn, #nextBtn { display: inline-block; margin-top: 45px; /* Increased margin */ margin-right: 10px; padding: 6px 16px; /* Adjusted padding */ background-color: #63a3ad; /* Changed background color */ color: white; /* Changed text color */ border: none; /* Removed outline */ border-radius: 5px; /* Adding border radius */ cursor: pointer; transition: background-color 0.3s ease, color 0.3s ease; font-size: 20px; /* Adjusting font size */ vertical-align: middle; /* Aligns buttons vertically */ } </style> <div id="quizContainer"> <div id="titleContainer"> <h1>Hitos del lenguaje<br><span id="age">15-18 meses</span></h1> </div> <div id="questionContainer"> <p><strong>Question 1:</strong><br>Is the sky blue?</p> </div> <form id="quizForm"> <div id="answerContainer"> <!-- 单选框将通过JS动态生成 --> </div> <button type="button" id="prevBtn">←</button> <!-- Left arrow character --> <button type="button" id="nextBtn">→</button> <!-- Right arrow character --> </form> </div> <script> document.addEventListener('DOMContentLoaded', function() { let questionNumber = 1; // 定义正确答案,用于后续计算得分 const correctAnswers = { 1: "yes", 2: "yes", 3: "no", 4: "yes" }; const questions = [ "Is the sky blue?", "Do you like pizza?", "Have you traveled abroad?", "Do you enjoy reading?" ]; const selectedAnswers = {}; // 存储用户选择的答案 const answerContainer = document.getElementById('answerContainer'); // 初始化第一题的单选框 renderAnswerOptions(questionNumber); // 初始隐藏返回按钮 document.getElementById('prevBtn').style.display = 'none'; // 渲染对应题目的单选框选项 function renderAnswerOptions(qNum) { // 清空容器并生成新的单选框 answerContainer.innerHTML = ` <input type="radio" id="yes${qNum}" name="q${qNum}" value="yes"> <label for="yes${qNum}" class="btn">Yes</label> <input type="radio" id="no${qNum}" name="q${qNum}" value="no"> <label for="no${qNum}" class="btn">No</label> `; // 恢复之前选中的答案 const selected = selectedAnswers[qNum]; if (selected) { document.querySelector(`input[name="q${qNum}"][value="${selected}"]`).checked = true; } else { // 无选中状态时清空 document.querySelectorAll(`input[name="q${qNum}"]`).forEach(radio => radio.checked = false); } } document.getElementById('nextBtn').addEventListener('click', function() { // 保存当前题目的答案 const answer = document.querySelector(`input[name="q${questionNumber}"]:checked`); if (answer) { selectedAnswers[questionNumber] = answer.value; } if (questionNumber < questions.length) { questionNumber++; // 更新题目文本 document.getElementById('questionContainer').innerHTML = `<p><strong>Question ${questionNumber}:</strong><br>${questions[questionNumber - 1]}</p>`; // 渲染当前题目的单选框 renderAnswerOptions(questionNumber); // 显示返回按钮 document.getElementById('prevBtn').style.display = 'inline-block'; // 切换按钮文本 if (questionNumber === questions.length) { document.getElementById('nextBtn').innerText = 'See Results'; } } else { // 计算答对数量 let correctCount = 0; Object.keys(correctAnswers).forEach(qNum => { if (selectedAnswers[qNum] === correctAnswers[qNum]) { correctCount++; } }); console.log(`答对题目数量:${correctCount}`); // 根据得分跳转页面,示例: if (correctCount === 4) { // window.location.href = 'perfect-score.html'; alert('全部答对!跳转至满分页面'); } else if (correctCount >= 2) { // window.location.href = 'good-score.html'; alert('答对一半以上,跳转至良好页面'); } else { // window.location.href = 'low-score.html'; alert('答对较少,跳转至基础页面'); } } }); document.getElementById('prevBtn').addEventListener('click', function() { if (questionNumber > 1) { // 保存当前题目的答案 const answer = document.querySelector(`input[name="q${questionNumber}"]:checked`); if (answer) { selectedAnswers[questionNumber] = answer.value; } questionNumber--; // 更新题目文本 document.getElementById('questionContainer').innerHTML = `<p><strong>Question ${questionNumber}:</strong><br>${questions[questionNumber - 1]}</p>`; // 渲染当前题目的单选框 renderAnswerOptions(questionNumber); // 切换按钮文本 document.getElementById('nextBtn').innerText = 'Next'; // 隐藏返回按钮(当回到第一题时) if (questionNumber === 1) { document.getElementById('prevBtn').style.display = 'none'; } } }); }); </script>
关键修复点说明
- 动态生成单选框:新增
renderAnswerOptions函数,每次切换题目时生成对应qX的单选框,确保每个题目有独立的name和id,避免状态冲突。 - 修正选择器语法:将错误的
input[name="qX"]:[value="Y"]改为正确的input[name="qX"][value="Y"],能准确定位到目标单选框。 - 完善答案保存逻辑:点击「返回」按钮时也会保存当前题目的答案,避免丢失未提交的选择。
- 添加得分计算与跳转:新增
correctAnswers对象存储正确答案,完成测验后计算答对数量,根据得分执行跳转逻辑(示例用alert展示,可替换为实际跳转代码)。 - 优化按钮显示逻辑:第一题时隐藏「返回」按钮,切换到最后一题时「下一步」按钮变为「查看结果」。
内容的提问来源于stack exchange,提问作者Bernardo
相关产品推荐
相关产品推荐

