Vue2中v-on绑定nextBtn函数报错及问答切换方案咨询
解决Vue2答题组件Next按钮报错及功能实现
错误原因分析
nextBtn、answers等DOM元素变量仅在mounted或局部方法中定义,nextBtn方法中直接引用导致ReferenceError- 过度操作DOM,违背Vue数据驱动的核心思想,应该通过状态变量控制UI变化
backBtn方法中错误使用this.question,实际应操作this.currentQuestioncalculateResult使用箭头函数导致this指向错误,无法访问组件实例
修改后的完整代码
HTML
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app1"> <display-question></display-question> </div>
JS
Vue.component('display-question', { data: function() { return { currentQuestion: 0, answered: 0, showWrongQuestion: false, wrongQuestions: [], wrongAnswers: 0, correctAnswers: 0, message: "Enter your answer here", WhatAnswer: "default", // 新增状态控制按钮禁用和选中样式 isNextDisabled: true, selectedAnswerIndex: null, showResult: false, questions: [ { question: 'What is the capital of Ukrain ?', answer: ['Kyiv', 'Kabul', 'Buenos Aires', 'Praia'], correct_answer: 0, selected: null, sense: 0 }, { question: 'When was Queen Elizabeth II death ?', answer: ['11/09/2022', '08/09/2022', '12/08/2022', '07/09/2022'], correct_answer: 1, selected: null, sense: 0 }, { question: 'How many bones are there in human body?', answer: ['206', '186', '209', '190'], correct_answer: 0, selected: null, sense: 0 }, { question: 'Who were the 30th president of ?', answer: ['Julia Eileen Gillard', 'John Winston Howard ', 'Scott John Morrison ', 'Anthony Albanese'], correct_answer: 2, selected: null, sense: 0 }, { question: 'What is the biggest continent?', answer: ['Oceania', 'Europe', 'Asia', 'Africa'], correct_answer: 2, selected: null, sense: 0 } ] } }, methods: { backBtn: function() { // 修正变量名错误 if (this.currentQuestion > 0) { this.currentQuestion--; // 返回上一题时同步选中状态 this.selectedAnswerIndex = this.questions[this.currentQuestion].selected; this.isNextDisabled = this.selectedAnswerIndex === null; } }, nextBtn: function() { this.answered < this.questions.length ? this.answered++ : ''; if (this.currentQuestion < this.questions.length - 1) { // 保存当前题的选中答案 this.questions[this.currentQuestion].selected = this.selectedAnswerIndex; // 切换到下一题 this.currentQuestion++; // 重置下一题的选中状态和按钮禁用 this.selectedAnswerIndex = this.questions[this.currentQuestion].selected; this.isNextDisabled = this.selectedAnswerIndex === null; } else { // 计算最终结果 this.questions.forEach(question => { if (question.sense === 0) { if (question.selected == question.correct_answer) { this.correctAnswers++; } else { this.wrongAnswers++; this.wrongQuestions.push({ answers: question.answer, question: question.question, correct_answer: question.correct_answer, selected: question.selected }); } question.sense = 1; } }); // 显示结果面板 this.showResult = true; } }, calculateResult: function() { return (this.correctAnswers / this.questions.length) * 100; }, selectAnswer: function(index) { // 通过状态控制选中,不再操作DOM this.selectedAnswerIndex = index; this.isNextDisabled = false; } }, template: ` <div> <div v-if="!showResult"> <h2>{{ questions[currentQuestion].question }}</h2> <br> <!-- 通过状态绑定class控制选中样式 --> <span class="answer" v-for="(answer, index) in questions[currentQuestion].answer" :key="index" @click="selectAnswer(index)" :class="{ selected: selectedAnswerIndex === index }" > {{ answer }} </span> <p> <button class="backBtn" @click="backBtn" :disabled="currentQuestion === 0">BACK</button> <!-- 通过状态控制按钮禁用 --> <button class="next-btn" @click="nextBtn" :disabled="isNextDisabled"> {{ currentQuestion < (questions.length -1) ? "Next" : "Result!" }} </button> </p> </div> <div v-if="showResult" class="result"> <div class="success"> <h3>答题结果</h3> <p>正确答案:{{ correctAnswers }}/{{ questions.length }}</p> <p>正确率:{{ calculateResult().toFixed(2) }}%</p> <h4>错题列表</h4> <div v-for="(item, index) in wrongQuestions" :key="index"> <p>{{ item.question }}</p> <p>你的答案:{{ item.answers[item.selected] }}</p> <p>正确答案:{{ item.answers[item.correct_answer] }}</p> </div> </div> </div> </div> `, }) var test1 = new Vue({ el: "#app1", data: {}, });
关键修改说明
- 移除DOM操作:新增
isNextDisabled、selectedAnswerIndex、showResult状态变量,通过Vue的响应式绑定控制按钮禁用、答案选中样式、结果面板显示 - 修复变量作用域问题:不再直接引用DOM元素变量,所有逻辑通过组件状态实现
- 修正方法错误:
backBtn方法修正为操作this.currentQuestion,calculateResult改用普通函数保证this指向组件实例 - 完善状态同步:切换题目时同步保存当前题的选中状态,返回上一题时恢复选中状态
- 增强用户体验:Back按钮在第一题时禁用,结果面板显示正确率和错题详情
内容的提问来源于stack exchange,提问作者James Pumkin
相关产品推荐
相关产品推荐

