<template>
<div class="quiz-container">
<div class="quiz-info">
<h1>知识问答挑战</h1>
<div class="question-number">题目 {{ currentQuestionIndex + 1 }}/{{ totalQuestions }}</div>
</div>
<div class="progress-bar">
<div class="progress" :style="{width: progressWidth}"></div>
</div>
<!-- 核心:只渲染3个主要DOM元素 -->
<!-- 1. 题目容器 -->
<div class="question-container" v-once>
<h2 class="question-title">{{ currentQuestion.text }}</h2>
</div>
<!-- 2. 选项容器 -->
<div class="options-container">
<div
v-for="(option, index) in currentQuestion.options"
:key="index"
class="option"
:class="{selected: selectedOption === index}"
@click="selectOption(index)"
>
<input
type="radio"
:id="'option'+index"
:value="index"
:checked="selectedOption === index"
>
<label :for="'option'+index">
<strong>{{ String.fromCharCode(65 + index) }}.</strong> {{ option.text }}
</label>
</div>
</div>
<!-- 3. 导航按钮容器 -->
<div class="nav-buttons">
<button
class="nav-btn prev-btn"
:disabled="currentQuestionIndex === 0"
@click="prevQuestion"
>
← 上一题
</button>
<div class="counter">已答:{{ answeredCount }}/{{ totalQuestions }}</div>
<button
class="nav-btn next-btn"
:disabled="selectedOption === null"
@click="nextQuestion"
>
{{ isLastQuestion ? '完成答题' : '下一题 →' }}
</button>
</div>
</div>
</div>
</template>
<script>
export default {
data: {
questions: this.generateQuestions(50),
currentQuestionIndex: 0,
selectedOption: null,
userAnswers: [],
totalQuestions: 50
},
computed: {
// 当前问题数据
currentQuestion() {
return this.questions[this.currentQuestionIndex];
},
// 进度条宽度
progressWidth() {
return `${((this.currentQuestionIndex + 1) / this.totalQuestions) * 100}%`;
},
// 是否为最后一题
isLastQuestion() {
return this.currentQuestionIndex === this.totalQuestions - 1;
},
// 已答题目数量
answeredCount() {
return this.userAnswers.filter(answer => answer !== null).length;
}
},
methods: {
// 生成模拟题目数据
generateQuestions(count) {
const questions = [];
const topics = ['JavaScript', 'CSS', 'HTML', 'Vue.js', 'React', 'Node.js', 'HTTP协议', '算法'];
const difficulty = ['简单', '中等', '困难'];
for (let i = 0; i < count; i++) {
const topic = topics[Math.floor(Math.random() * topics.length)];
const diff = difficulty[Math.floor(Math.random() * difficulty.length)];
questions.push({
id: i + 1,
text: `以下关于${topic}的叙述中,哪项是${diff}级的知识点?`,
options: [
{ text: '正确选项', value: true },
{ text: '干扰选项1', value: false },
{ text: '干扰选项2', value: false },
{ text: '干扰选项3', value: false }
]
});
}
return questions;
},
// 选择选项
selectOption(index) {
this.selectedOption = index;
},
// 上一题
prevQuestion() {
if (this.currentQuestionIndex > 0) {
this.currentQuestionIndex--;
// 恢复用户之前的选择(如果有)
this.selectedOption = this.userAnswers[this.currentQuestionIndex];
}
},
// 下一题
nextQuestion() {
// 保存用户答案
this.userAnswers[this.currentQuestionIndex] = this.selectedOption;
if (!this.isLastQuestion) {
this.currentQuestionIndex++;
// 重置选择状态,如果之前有答案则恢复
this.selectedOption = this.userAnswers[this.currentQuestionIndex] || null;
} else {
// 最后一题完成
this.showResults();
}
},
// 显示结果
showResults() {
const correctCount = this.userAnswers.reduce((count, selected, index) => {
return count + (selected !== null && this.questions[index].options[selected].value ? 1 : 0);
}, 0);
alert(`答题完成!\n共答对 ${correctCount} 题\n正确率: ${(correctCount/this.totalQuestions*100).toFixed(1)}%`);
// 重置测试
this.currentQuestionIndex = 0;
this.userAnswers = [];
this.selectedOption = null;
}
}
}
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Microsoft YaHei', sans-serif;
}
body {
background-color: #f5f7fa;
padding: 20px;
}
.quiz-container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
overflow: hidden;
padding: 25px;
position: relative;
}
.progress-bar {
height: 8px;
background-color: #e9ecef;
border-radius: 4px;
margin-bottom: 25px;
position: relative;
overflow: hidden;
}
.progress {
height: 100%;
background: linear-gradient(90deg, #4c6ef5, #228be6);
transition: width 0.4s ease;
}
.question-container {
background-color: #f8f9fa;
border-radius: 8px;
padding: 20px;
margin-bottom: 25px;
min-height: 150px;
transition: all 0.4s ease;
}
.question-title {
font-size: 18px;
color: #343a40;
line-height: 1.6;
margin-bottom: 20px;
}
.options-container {
display: flex;
flex-direction: column;
gap: 15px;
}
.option {
display: flex;
align-items: center;
background: white;
border: 2px solid #e9ecef;
border-radius: 8px;
padding: 14px 20px;
cursor: pointer;
transition: all 0.2s;
}
.option:hover {
background-color: #f1f3f5;
border-color: #ced4da;
}
.option.selected {
background-color: #edf2ff;
border-color: #4c6ef5;
}
.option input {
margin-right: 15px;
cursor: pointer;
}
.option label {
cursor: pointer;
font-size: 16px;
color: #495057;
flex-grow: 1;
}
.nav-buttons {
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-btn {
padding: 12px 25px;
background-color: #4263eb;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
}
.nav-btn:hover {
background-color: #3b5bdb;
transform: translateY(-2px);
}
.nav-btn:disabled {
background-color: #adb5bd;
cursor: not-allowed;
transform: none;
}
.prev-btn {
background-color: #868e96;
}
.prev-btn:hover {
background-color: #495057;
}
.counter {
font-size: 15px;
color: #868e96;
}
.quiz-info {
margin-bottom: 15px;
display: flex;
justify-content: space-between;
align-items: center;
}
.question-number {
font-weight: bold;
color: #4263eb;
font-size: 16px;
}
</style>
修改一下
最新发布