javascript - Vue 调查没有索引问题
问题描述
我必须在 vue.js 中构建一个测验/调查应用程序,我对 vue 还是很陌生,并且仍在尝试学习它。我有一个测验/调查,根据用户在初始问题中的回答提出不同的问题。
因此,如果用户选择是,它将显示问题 2,如果用户选择否,它将显示问题 3,依此类推。
我不确定最好的解决方法是什么,但到目前为止我有这个。
无论如何我可以在一个人点击下一步后将我的答案的值用作 questionIndex 吗?
JS文件:
"use strict";
let quiz = {
title: "Asbestos Quiz",
questions: [
{
text: 'Do you need help with an Asbestos Survey?',
answers: [
{
text: "Yes",
value: '2'`enter code here`
},
{
text: "No",
value: '3'
},
]
},
{
text: 'Was your property constructed pre 2000',
answers: [
{
text: "Yes",
value: '4'
},
{
text: "No",
value: '5'
},
]
},
{
text: 'Do you need an Asbestos Management plan?',
answers: [
{
text: "Yes",
value: '6'
},
{
text: "No",
value: '7'
},
]
}
]
};
var app = new Vue({
el: "#app",
data: {
quiz: quiz,
questionIndex: 0,
responses: [],
errors: [],
error: ''
},
methods: {
prev: function() {
this.questionIndex--;
},
next: function() {
if (this.responses[this.questionIndex] === undefined) {
this.errors[this.questionIndex] = 1;
this.error = 'Please select your answer';
}
else {
this.errors[this.questionIndex] = 0;
this.questionIndex++;
}
},
score: function() {
},
playAgain: function() {
this.questionIndex = 0;
}
}
});
HTML:
<html lang="en">
<head>
<title>Vue quiz/survey</title>
<meta name="viewport" content="width=device-width"/>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- <link rel="stylesheet" href="index.css"> -->
</head>
<body>
<div id="app">
<div class="container">
<div class="jumbotron mt-3">
<h1 class="mb-5">{{ quiz.title }}</h1>
<hr>
<p v-if="errors[questionIndex]" class="alert alert-danger">
{{ error }}
</p>
<div v-for="(question, index) in quiz.questions">
<div v-show="index === questionIndex">
<h4 class="mt-5 mb-3">{{ question.text }}</h4>
<div v-for="answer in question.answers" class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio"
:value="answer.value"
:name="index"
v-model="responses[index]">
{{answer.text}}
</label>
</div>
<div class="mt-5">
<button
class="btn btn-primary"
v-if="questionIndex > 0"
@click="prev">
prev
</button>
<button class="btn btn-secondary" @click="next">
next
</button>
</div>
</div>
</div>
<div v-show="questionIndex === quiz.questions.length">
<h3>Your Results</h3>
<p>
You are: {{ score() }}
</p>
<button class="btn btn-success" @click="playAgain">
Play Again!
</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
解决方案
我认为这听起来像是一个可能很有趣的练习,所以我花了一些时间在一个 Vue CLI 沙盒应用程序中创建一个实现,我构建并使用它来尝试各种想法。
我学到了一些东西,希望你能从中有所收获。如果您决定喜欢它并希望自己实现它,我会将“以前的”功能作为 TODO 保留。
测验问题.vue
<template>
<div class="quiz-questions">
<div class="jumbotron mt-3">
<h1 class="mb-5">{{ quiz.title }}</h1>
<hr>
<question v-if="!showResults" :question="currentQuestion" @answer-selected="processAnswer" />
<div class="mt-5">
<button class="btn btn-primary" v-if="currentQuestionId > 1 && !showResults" @click="getPreviousQuestion">
prev
</button>
<button v-if="!showResults" class="btn btn-secondary" @click="getNextQuestion">
{{ nextButtonLabel }}
</button>
</div>
<div v-if="showResults">
<h3>Your Results</h3>
<table class="table table-bordered">
<thead>
<tr>
<th>QUESTION</th>
<th>ANSWER</th>
</tr>
</thead>
<tbody>
<tr v-for="(response, index) in responses" :key="index">
<td>{{ getQuestionText(response.questionId) }}</td>
<td>{{ getAnswerText(response.answerId) }}</td>
</tr>
</tbody>
</table>
<button class="btn btn-success" @click="playAgain">
Play Again!
</button>
</div>
</div>
</div>
</template>
<script>
import quiz from './quiz.js';
import Question from '@/components/stackoverflow/Question'
export default {
components: {
Question
},
data() {
return {
quiz: quiz,
currentQuestionId: 1,
currentAnswerId: 1,
previousQuestionId: 0,
responses: [],
showResults: false,
errors: [],
error: ''
}
},
computed: {
currentQuestion() {
return this.quiz.questions.find( question => {
return question.id === this.currentQuestionId;
})
},
nextQuestionId() {
let retVal = 0;
if (this.currentAnswerId > 0) {
let tempAnswer = this.currentQuestion.answers.find( answer => {
return answer.id === this.currentAnswerId;
});
retVal = tempAnswer.nextQuestionId;
}
return retVal;
},
lastQuestion() {
return this.currentQuestion.answers[0].nextQuestionId === 0;
},
nextButtonLabel() {
return this.lastQuestion ? 'Finish' : 'Next';
}
},
methods: {
getPreviousQuestion() {
this.currentQuestionId = this.previousQuestionId;
},
getNextQuestion() {
// TODO: Look for existing response for this question in case the 'Previous' button was pressed
// If found, update answer
// Store current question id and answer id in responses
let response = { questionId: this.currentQuestionId, answerId: this.currentAnswerId };
this.responses.push(response);
if (this.lastQuestion) {
this.showResults = true;
return;
}
this.previousQuestionId = this.currentQuestionId;
this.currentQuestionId = this.nextQuestionId;
//console.log(this.responses);
},
getQuestionText(id) {
let result = this.quiz.questions.find( question => {
return question.id === id;
});
return result.text;
},
getAnswerText(id) {
// NOTE: Since answers are currently limited to '1 = Yes' and '2 = No',
// this method does not need to involve any look up
return id === 1 ? 'Yes' : 'No';
},
processAnswer(selectedAnswerId) {
this.currentAnswerId = selectedAnswerId;
},
score() {
return 'TODO'
},
playAgain() {
this.currentQuestionId = 1;
this.showResults = false;
this.responses = [];
}
}
}
</script>
问题.vue
<template>
<div class="question">
<h4 class="mt-5 mb-3">{{ question.text }}</h4>
<div class="form-check" v-for="(answer, idx) in question.answers" :key="idx">
<input class="form-check-input" type="radio"
:value="answer.id" v-model="answerId" @change="answerSelected">
<label class="form-check-label">
{{answer.text}}
</label>
</div>
</div>
</template>
<script>
export default {
props: {
question: {
type: Object,
required: true
}
},
data() {
return {
answerId: 1
}
},
watch:{
question() {
// Reset on new question
this.answerId = 1;
}
},
methods: {
answerSelected() {
this.$emit('answer-selected', this.answerId);
}
}
}
</script>
我还通过添加各种 ID 属性来帮助跟踪来修改您的测试数据,并创建了更多的占位符问题。
测验.js
const quiz = {
title: "Asbestos Quiz",
questions: [
{
id: 1,
text: 'Do you need help with an Asbestos Survey?',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 2
},
{
id: 2,
text: "No",
nextQuestionId: 3
},
]
},
{
id: 2,
text: 'Was your property constructed pre 2000',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 4
},
{
id: 2,
text: "No",
nextQuestionId: 5
},
]
},
{
id: 3,
text: 'Do you need an Asbestos Management plan?',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 6
},
{
id: 2,
text: "No",
nextQuestionId: 7
},
]
},
{
id: 4,
text: 'Question 4',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
},
{
id: 5,
text: 'Question 5',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
},
{
id: 6,
text: 'Question 6',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
},
{
id: 7,
text: 'Question 7',
answers: [
{
id: 1,
text: "Yes",
nextQuestionId: 0
},
{
id: 2,
text: "No",
nextQuestionId: 0
},
]
}
]
};
export default quiz;
推荐阅读
- android - Gatt 服务器服务列表为空
- javascript - 在 setState 中反应访问范围外的变量
- jekyll - Jekyll - 无法获取 url 和作者姓名
- javascript - 无法使用 Math.round 或 Math.ceil 对数字进行四舍五入
- asp.net - 对 asp.net 使用引导程序所需的验证,而不是 RequiredFieldvalidator
- c# - WPF 将文本写入图像并发送到打印机
- javascript - 如何使用 javascript 中的搜索文本对数组进行排序?
- python - 基于 Pandas 中唯一编号的两个 csv 文件之间的日期差异
- google-bigquery - Bigquery 查询 - 对分组数据的子选择进行事件计数
- mysql - 为什么此查询返回错误并且没有寄存器?