Vue.js 2中'answer'属性未定义报错的解决咨询
Vue.js 2 报错「Property or method 'answer' is not defined」排查与修复
核心报错原因
你的HTML模板里v-for遍历的数据源写了笔误:
原代码中写的是
<span v-for="(answer, index) in questions[currentQuestion].questions"
但你的questions数组里每个对象的选项列表属性是answers,不是questions。遍历不存在的属性导致渲染时触发answer未定义的错误。
完整修复方案
一、修复核心报错
把HTML中v-for的遍历源改成questions[currentQuestion].answers,同时修正点击事件的绑定方式(原用title绑定事件是错误的,改用Vue的@click):
<div class="answers"> <span v-for="(answer, index) in questions[currentQuestion].answers" :key="index" :data-index="index" @click="selectAnswer(index)">{{ answer }}</span> </div>
(顺便把这个容器的类名从question改成answers,避免和其他元素混淆)
二、修复其他代码问题
组件定义错误
- 组件名不能用JS关键字
function,改成合法名称(比如QuizComponent); - 组件的方法选项是
methods(复数),不是method; - 组件的
data必须返回一个对象,不能为空; - 组件需要通过
props接收父组件数据,不能直接访问根实例的属性(建议把业务逻辑统一放在根实例,避免组件职责混乱)。
- 组件名不能用JS关键字
DOM操作与事件逻辑错误
- 避免直接用
document.querySelector,改用Vue的$refs定位元素; selectAnswer方法中,原代码的a.currentChoice是错误的,直接传递点击的索引更简洁;- 按钮类名不一致:原代码按钮类是
next-btn,但JS里写的是nextbtn,统一为next-btn; - 箭头函数导致
this指向错误:calculateResult不能用箭头函数,改用普通函数保证this指向Vue实例。
- 避免直接用
业务逻辑错误
calculateResult里的判断条件应该是question.selected == question.correct_answer,不是question.correct;- 按钮禁用逻辑可以直接绑定数据:
:disabled="questions[currentQuestion].selected === null",不用手动操作DOM属性。
修正后的完整代码
HTML部分
<h1 class="main">Quiz app in Vue</h1> <div id="question"> <div class="user-role"> <div class="question current"> <transition name="slide-fade" mode="out-in"> <div :key="questions[currentQuestion].question" :class="{'deactivate': answered == questions.length}"> <h2>{{ questions[currentQuestion].question }}</h2> <div class="answers" ref="answersContainer"> <span v-for="(answer, index) in questions[currentQuestion].answers" :key="index" :data-index="index" @click="selectAnswer(index)">{{ answer }}</span> </div> </div> </transition> <div class="next-question"> <button class="next-btn" :disabled="questions[currentQuestion].selected === null" @click="nextQuestion">{{ currentQuestion < (questions.length -1) ? 'Next' : 'Result!' }}</button> </div> </div> <div class="result" ref="resultContainer"> <div class="success"></div> <h2>You have successfully finished the quiz, and your score is:</h2> <h1 :class="[(Number(((correctAnswers / questions.length) *100)).toFixed(2) >= 50) ? 'green' : 'red']">{{ Number(((correctAnswers / questions.length) *100)).toFixed(2) }}%</h1> <small><b>{{ correctAnswers }}</b> Correct, <b>{{ wrongAnswers }}</b> Wrong</small> <button class="close" @click="hideResult">close</button> <button class="show-wrong-ones" v-show="wrongAnswers > 0" @click="showWrongQuestion = true">Wrong answers</button> </div> </div> <div class="wrong-questions" v-show="showWrongQuestion"> <h2 v-if="wrongQuestions.length > 1">Your wrong Questions</h2> <h2 v-else-if="wrongQuestions.length == 1">Your wrong Question</h2> <div class="wrong-one" v-for="question in wrongQuestions" :key="question.question"> <h3>{{ question.question }}</h3> <div class="answers-container"> <span class="selected">{{ question.answers[question.selected] }}</span> <span class="correct">{{ question.answers[question.correct_answer] }}</span> </div> </div> <button id="return-to-result" @click="showWrongQuestion = false">Show my result</button> </div> </div>
Vue.js 2代码部分
new Vue ({ el: "#question", data() { return { questions: [ { question: 'What is the capital of Ukrain ?', answers: ['Kyiv', 'Kabul', 'Buenos Aires', 'Praia'], correct_answer: 0, selected: null, sense: 0 }, { question: 'When was Queen Elizabeth II death ?', answers: ['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?', answers: ['206', '186', '209', '190'], correct_answer: 0, selected: null, sense: 0 }, { question: 'Who was the 30th prime minister of Australia?', answers: ['Julia Eileen Gillard', 'John Winston Howard', 'Scott John Morrison', 'Anthony Albanese'], correct_answer: 2, selected: null, sense: 0 }, { question: 'What is the biggest continent?', answers: ['Oceania', 'Europe', 'Asia', 'Africa'], correct_answer: 2, selected: null, sense: 0 } ], showWrongQuestion: false, wrongQuestions: [], currentQuestion: 0, answered: 0, wrongAnswers: 0, correctAnswers: 0 } }, methods: { selectAnswer(index) { // 移除所有选中状态 const answers = this.$refs.answersContainer.querySelectorAll('span'); answers.forEach(answer => answer.classList.remove('selected')); // 给当前点击的选项加选中状态 answers[index].classList.add('selected'); // 记录选中的选项索引 this.questions[this.currentQuestion].selected = index; }, nextQuestion() { if (this.currentQuestion < this.questions.length - 1) { this.currentQuestion++; } else { this.calculateResult(); this.showResult(); } }, calculateResult() { this.correctAnswers = 0; this.wrongAnswers = 0; this.wrongQuestions = []; this.questions.forEach(question => { if (question.selected === question.correct_answer) { this.correctAnswers++; } else { this.wrongAnswers++; this.wrongQuestions.push({...question}); } }); }, showResult() { this.$refs.resultContainer.classList.add('active'); document.querySelector('.question.current').classList.add('blur'); }, hideResult() { this.$refs.resultContainer.classList.remove('active'); document.querySelector('.question.current').classList.remove('blur'); } } });
内容的提问来源于stack exchange,提问作者James Pumkin
相关产品推荐
相关产品推荐

