技术:vue3 + js + vant3
轮播里面可以内嵌图片也可以内嵌具体的内容。那么,依据我司需求,需要实现完成一个做题的题库。
需求:
- 当点击的时候,被点击的答案变色,进入下一题
- 当有上一题的时候,显示 ‘上一题’,下一题 是以及答题完毕的状态需要显示出 ‘下一题’
- 显示出当前题号
- 内涵引导页和结论页
- bug: 点击过快导致题录录入异常(具体解决方法也在下面了)
具体实现看代码注释啦~
js部分:
// swipe组件
const swipe = ref(null)
// 当前题号
const topicIndex = ref(0)
// 题目开始位置 (前面多少个引导页)
const topicStartPosition = 1
// 是否处于答题界面
const isAnswerPage = ref(false)
// 当前页面是否答题完毕
const hadQuestion = ref(false)
//题库 里面放个格式示例,方便大家看懂结构。这边省略了从后端获取题库的步骤了,大家把题目放到这里面即可
const questionBank = reactive({
data: [
{
"id":71,
"title":"喜欢吃苹果吗",
"group":"food",
"hit":null,
"score":null
"question":[
{
"id":1,"score":0,"question":"喜欢"},
{
"id":2,"score":2,"question":"不喜欢"}],
})
//解决点击过快导致题目录入异常
const isDisabled = ref(false)
// 点击选择答案,录入分数
const hitQuestion = (score, index) => {
questionBank.data[index].score = score
nextQuestion()
setTimeout(() => {
isDisabled.value = false
}, 300);
}
//监听题目变化
const topicChange = async (index) => {
// index 为当前轮播组件索引
topicIndex.value = index - topicStartPosition
// 判断当前页面是否答题完毕
hadQuestion.value = questionBank.data[index - topicStartPosition]?.hit !== null ? "true" : "false"
// 判断是否在答题页
isAnswerPage.value = index >= topicStartPosition && index <= questionBank.data.length + topicStartPosition - 1
const isGetAnswer = index < questionBank.data.length + topicStartPosition
// 判断是否完成题目
if (!isGetAnswer) {
//此刻questionBank.data里面是做好的题目,处理成后端需要的结果就行
}
}
// 切换题目
const previousQuestion = () => swipe.value.prev()
const nextQuestion = () => swipe.value.next()
H5部分:
<van-swipe class="swipe-box"
:loop="false"
:show-indicators="false"
:touchable="false"
@change="topicChange"
ref="swipe">
<!-- 引导页 -->
<van-swipe-item>
</van-swipe-item>
<!-- 答题页 -->
<van-swipe-item class="selectedAnswer"
v-for="(selecting, topicIndex) in questionBank.data"
:key="selecting.id">
<!-- 标题 -->
<div class="answer-page-title">
<div>{
{ selecting.title }}</div>
</div>
<!-- 选项 -->
<van-radio-group v-model="questionBank.data[topicIndex].hit">
<van-radio class="radio"
v-for="(item, optionIndex) in selecting.question"
:name="optionIndex"
:key='item.id'>
<template #icon="props">
<!-- 这里增加disabled,是为了防止重复点击出现bug -->
<van-button class="options-button only-options-btn"
:class="props.checked ? 'options-button-active' : ''"
size="large"
:disabled="isDisabled"
plain
block
@click="hitQuestion(item.score,topicIndex)">
<span>{
{ item.question }}</span>
</van-button>
</template>
</van-radio>
</van-radio-group>
</van-swipe-item>
<!-- 结论页 -->
<van-swipe-item class="conclusion-page">
</van-swipe-item>
</van-swipe>
<!-- 分页 -->
<div class="pagination"
v-show="isAnswerPage">
<div :class="topicIndex === 0? 'visibility' : ''"
@click="previousQuestion">
<svg class="icon"
aria-hidden="true">
<use xlink:href="#icon-prev"></use>
</svg>上一题
</div>
<!-- 页数 -->
<div class="progress-number">
{
{ topicIndex + 1}}<span class="progress-mom">/{
{ questionBank.data.length }}</span>
</div>
<div :class="hadQuestion === 'false' ? 'visibility' : ''"
@click="nextQuestion">
下一题<svg class="icon"
aria-hidden="true">
<use xlink:href="#icon-next"></use>
</svg>
</div>
</div>
style
.visibility {
visibility: hidden;
}
//我们需要禁止点击按钮的功能 但是并不需要样式也改变
:deep(.van-button--disabled) {
opacity: 100%;
}
// 选项按钮激活状态
.options-button-active,
.button-purple {
color: #ffffff;
background-color: #0ef362;
}