IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue实现单选做题根据对错标色,作对跳转下一题,实现思路详解 -> 正文阅读

[JavaScript知识库]vue实现单选做题根据对错标色,作对跳转下一题,实现思路详解

vue实现单选做题效果详解

最近在做一个答题项目,废了好多时间,经过折腾和在大佬的指导下,终于清晰的了解逻辑,如果你也遇到此类问题,不妨先看看我的思路,看完点个赞,那是继续跟新的动力

此案例是使用swiper以及vue来完成的。

需求分析,当点击了正确答案,选项背景色成指定的颜色,并且有一个打勾的效果,不能在选择其他选项,错误选项背景色改成对应的颜色,打上一个小叉,答对了自动切换到下一个题目,点击选项显示对应的答案及其解析。

主要涉及的知识点,vue 动态绑定class ,条件渲染,话不多说,首先先来看看效果

在这里插入图片描述
在这里插入图片描述

先详解在,在上源码,

先看布局,这里可以自己根据需求来布局

  <div  v-cloak id='app' class="recommendPage">
        <div class="swiper-container">
            <div class="swiper-wrapper">
                <div class="swiper-slide" v-for="(item, index) in tmList" :key="index">
                    <div class="box">
                        <van-divider class="qes-num"> {{ index + 1 }}/{{tmList.length}}</van-divider>
                        <p class="title">{{item.title}}</p>
                        <div class="anlist">
                            <ul>

								<li :class="{
						    	'success-active': item.userAnswer === subIndex,
								'error-active':item.userAnswer!==item.correct && item.userAnswer === subIndex}"
												v-for="(sub, subIndex) in item.answer" :key="sub.id" class="lis"
												@click="chechan(item,sub,  index,subIndex)">
									{{ sub }}
								 </li>
                            </ul>
                        </div>
                        <div v-if="isShowAnswer===index||item.userAnswer!==-1">
                            <div class="mar20">
                                正确答案: <span class="redcol"> {{ item.answer[item.correct] }}</span>
                            </div>
                            <div class="mar20 pa20">解析: {{ item.content }}</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

再看逻辑

<script>
    const app = new Vue({
        el: "#app",
        data() {
            return {
                swiper: {},
                isShowAnswer: -1,// 控制是否显示解析
                isActive: -1,
                tmList: [
                    {
                        id: 1,
                        title: '1、1947年12月,毛泽东在《目前形势和我们的任务》中总结出十大军事原则,其核心是( )',
                        correct: 0,
                        answer: [
                            'A.集中优势兵力,各个歼灭敌人',
                            'B.诱敌深入,积极防御',
                            'C.多种作战形式,适时转变',
                            'D.避其主力,打其虚弱'
                        ],
                        userAnswer: -1,  
                        content: "毛泽东于1947年12月25日在中共中央召开的会议上所做《目前形势和我们的任务》的报告中正式提出十大军事原则。十大军事原则是一个有机的整体,其核心是强调集中优势兵力打歼灭战", 
                    },
                    {
                        id: 2,
                        title: '2、中国宋代哲学家朱熹提出“理在事先”,把“天理”说成是世界万物的本原。这是一种( )',
                        correct: 1,
                        answer: ['A.主观唯心主义观点', 'B.客观唯心主义观点', 'C.朴素唯物主义观点', 'D.形而上学唯物主义观点'],
                        userAnswer: -1,  
                        content: "主观唯心主义认为物质是某种主观精神的产物,客观唯心主义将物质归结为某种客观精神的产物。结合题干可得,“理在事先”这种“天理”观属于客观唯心主义。",
                    },
                    {
                        id: 3,
                        title: '3、毛泽东在《新民主主义论》中提出的新民主主义文化纲领是( )',
                        correct: 2,
                        answer: [
                            'A.为抗战服务',
                            'B.为工农兵服务',
                            'C.民族的、科学的、大众的文化',
                            'D.古为今用,洋为中用'
                        ],
                        userAnswer: -1, 
                        content: "新民主主义的文化就是“无产阶级领导的,人民大众的,反帝反封建的文化”。这种文化是无产阶级领导的民族的、科学的、大众的文化。",
                    },
					{
					    id: 4,
					    title: '4、下列选项中,强调外因在事物发展中起着重要作用的是( )',
					    correct: 2,
					    answer: [
					        'A.出淤泥而不染',
					        'B.威武不能屈,贫贱不能移',
							'C.近朱者赤,近墨者黑',
							'D.常在河边走,就是不湿鞋'
					    ],
					    userAnswer: -1, 
					    content: "在因果联系中,内因是事物变化的根据,外因是事物变化的条件。“近朱者赤,近墨者黑”强调的是外因在事物变化发展中的重要作用。",
					}
                ],
            }
        },
        methods: {
            chechan(v1, v2, index, index1) {
		      
                if (v1.userAnswer !== -1) return // 代表已经答过了
                this.isActive = index1//选中当前选项
                this.isShowAnswer = index //选完显示答案和解析
                 v1.userAnswer = index1;   //此处非常关键,已经改变了 tmList数组
                if (index1 === v1.correct) {
                    this.nextto();
                } 
                console.log("点击的答案" + v1, "正确答案" + `${v2}`, "第" + `${index + 1}` + "题", `点击了第${index + 1}题的第${index1 + 1}答案`);
           
				//判断最后一个  此判断只适用于最后一个题目的答案 和没一道题的 选项唯一   根据自己的业务判断最后一个题
				let clicklast = v1.content;
                let arrlast = this.tmList[this.tmList.length-1].content;
				if(clicklast==arrlast){
				       alert("恭喜你完成答题")
				}
				
            },

            nextto() {
                //获取当前索引
                let thisindex = this.swiper.activeIndex;
                this.swiper.slideTo(thisindex + 1, 1000, false);
            },
        },
        mounted() {
            let that = this;
            that.swiper = new Swiper('.swiper-container', {
                initialSlide: 0, //默认显示
		        autoplay:false,//等同于以下设置
                on: {
                    touchStart: function () {
                        // alert(this.activeIndex);//切换结束时,告诉我现在是第几个slide
                    },
                },
            })
        },
        created() {
             
        }
    });
</script>
  • 1.先来看最简单的 显示对应题目的解析和答案
isShowAnswer===index||item.userAnswer!==-1

首先isShowAnswer 默认值为-1.index就是当前题目的下标,只有当isShowAnswer和下标相等的时候,就显示,所以在点击事件中只需要将isShowAnswer 与当前题目的下标相等即可。this.isShowAnswer = index,显然这样是可以显示对应的题目的解析答案,当我们切下一个题目的时候,在滑动回来上一题,刚才显示的答案又被影藏了,显然是下标不等了,观察数据结构,每一个题目中都有一个userAnswer: -1,的字段,那么我们点击选项的时候,我们就将这个值变成点击的答案的下标,v1.userAnswer = index1;往上自己了解这一句,这一句非常关键,这里的参数v1也就是题目的每一条数据,神奇的是,你可以通过打印,如果你这样赋值之后,加入我们点击的是第一道题目的第一个选项,题目数组中的第一条数据将变成

 {
 id: 1,
     title: '1、1947年12月,毛泽东在《目前形势和我们的任务》中总结出十大军事原则,其核心是( )',
     correct: 0,
     answer: [
         'A.集中优势兵力,各个歼灭敌人',
         'B.诱敌深入,积极防御',
         'C.多种作战形式,适时转变',
         'D.避其主力,打其虚弱'
     ],
     userAnswer: 0,  
     content: "毛泽东于1947年12月25日在中共中央召开的会议上所做《目前形势和我们的任务》的报告中正式提出十大军事原则。十大军事原则是一个有机的整体,其核心是强调集中优势兵力打歼灭战", 
userAnswer: 0, 

所以我们在加上一个条件 ||item.userAnswer!==-1,这样当我们做过题目之后,每条数据的userAnswer字段经等于点击答案的下标,不在是-1,从而只要我们答题过后,切换回来,刚才显示的答案依然还是显示出来。

  • 2.再看正确答案标色
    我们给每一个答案都动态绑定一个一个样式
:class="{
'success-active': item.userAnswer === subIndex,
'error-active':item.userAnswer!==item.correct && item.userAnswer === subIndex}"
v-for="(sub, subIndex) in item.answer" :

从字面上不难看出,一个是正确的样式,一个是错误的样式。

item.userAnswer === subIndex

从点击事件中不难看出 v1.userAnswer = index1;点击了哪个答案就让他 添加上success-active的样式,那有的小伙伴想。万一我点击的是错误的答案呢,不要着急,仔细看error-active 它还需要&& 一个条件才成立item.userAnswer!==item.correct
从数据结构中不难看出

 {
 id: 1,
 title: '1、1947年12月,毛泽东在《目前形势和我们的任务》中总结出十大军事原则,其核心是( )',
 correct: 0,
 answer: [
     'A.集中优势兵力,各个歼灭敌人',
     'B.诱敌深入,积极防御',
     'C.多种作战形式,适时转变',
     'D.避其主力,打其虚弱'
 ],
 userAnswer: -1,  
 content: "毛泽东于1947年12月25日在中共中央召开的会议上所做《目前形势和我们的任务》的报告中正式提出十大军事原则。十大军事原则是一个有机的整体,其核心是强调集中优势兵力打歼灭战", 
},
correct字段标识正确答案的选项,0就是`answe`r中的第一项,那表示第一个就是正确答案

所以取值正确答案即为 正确答案: <span class="redcol"> {{ item.answer[item.correct] }}</span>

比如第一题 ,当我们本来正确答案是A,假如我蛮点击了B,那此时 userAnswer是不是等于了1 ,1不等于correct是不是代表我们选择错误的答案。所以只要保证item.userAnswer!==item.correct && item.userAnswer === subIndex 说明我们点击的就是错误的。

最后再看,

  if (v1.userAnswer !== -1) return 

本来每一个数组中的每一条数据userAnswer都是1-只要点击过后,userAnswer就等于点击的答案下标,所以下一次点击的时候,表示这个题目已点击过了,直接return不在往下执行。

最后说一下打勾打叉。其实就是条件添加上对用的class之后,我们给当前类添加一个伪类样式即可。

  .anlist .success-active::before{
            position: absolute;
            content: "?";
            top: 8px;
            left: 2px;
            font-size: 25px;
            color: #80e4ba;
        }
   .anlist .error-active::before{
            position: absolute;
            content: "×";
            top: 8px;
            left: 2px;
            font-size: 35px;
            color: #80e4ba;
        }

是不是没有想象中的那么复杂。

不是到这里就完了,一些小伙伴会问。我们后端返回的数据结构不是这样的呀,里面就没有userAnswer=-1的字段呀,那这个就很简单了,拿到数据遍历。像每一条数据中增加这样的一个字段,那不就完事了。然后还有一种可能,correct正确答案给的不是下标那怎么办,举个例子

   {
   id: 3,
          title: '3、毛泽东在《新民主主义论》中提出的新民主主义文化纲领是( )',
          correct: 2,
          answer: [
              'A.为抗战服务',
              'B.为工农兵服务',
              'C.民族的、科学的、大众的文化',
              'D.古为今用,洋为中用'
          ],
          userAnswer: -1, 
          content: "新民主主义的文化就是“无产阶级领导的,人民大众的,反帝反封建的文化”。这种文化是无产阶级领导的民族的、科学的、大众的文化。",
                    },

此题目不难看出正确答案就是C
如果后端给的数据书correct:'C.民族的、科学的、大众的文化' 那也简单,拿correctanswer数组中匹配,找到对应的下标即可。

总一,万变不离其中,你难道后台数据,将你的数据格式处理成上面的格式完事,无非就是遍历,追加字段。匹配一系列问题,差不多都是数组对象的简单玩法

                        重要事情说三遍,写了我一个小时,做个好人
                         **点赞**   **点赞**   **点赞**
                             *唯一跟新的动力*

完整代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <link rel="stylesheet" href="https://unpkg.com/swiper@6.8.4/swiper-bundle.min.css">
    <script src="https://unpkg.com/swiper@6.8.4/swiper-bundle.min.js"> </script>
	<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css"/>
	<script src="https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js"></script>
    <title>单选做题</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
          [v-cloak]{
            display: none
        }
		#app{
			width: 100%;
			height: 100%;
		 overflow: scroll;
		}
        ul li {
            list-style: none;
        }

   
        /* swiper */
        .swiper-container {
            width: 100vw;
            height: 100vh;
            background: #fff;
		
        }
        .swiper-container .swiper-slide {
            width: 100%;
            height: 100%;
            background: #fff;
            color: #000;
            font-size: 16px;
        }

        /* swiper */
        .box {
            width: 94%;
            margin: 0 auto;
        }

        .qes-num {
            margin-left: 8px;
        }

        .anlist {
            margin-top: 15px;
        }

        .anlist ul li {
            padding: 10px 0px;
            background: #f6f6f6;
            margin: 5px;
            border-radius: 7px;
            text-indent: 12px;
            overflow: hidden;
			text-overflow: ellipsis;
			white-space: nowrap;
        }

        .anlist .success-active {
            background: #021a02ad;
            color: #fff;
            position: relative;
        }

        .anlist .success-active::before{
            position: absolute;
            content: "?";
            top: 8px;
            left: 2px;
            font-size: 25px;
            color: #80e4ba;
        }

        .anlist .error-active {
            background: #c15a5a;
            color: #fff;
            position: relative;
        }
        .anlist .error-active::before{
            position: absolute;
            content: "×";
            top: 8px;
            left: 2px;
            font-size: 35px;
            color: #80e4ba;
        }
        .van-radio {
            margin: 10px 0px;
        }

        .redcol {
            color: red;
        }

        .mar20 {
            margin: 20px auto;
        }
		.pa20{
		background: #7c937014;
		    padding: 10px;
		    border-radius: 10px;
		    font-size: 14px;
		    color: #999;
		    line-height: 28px;
		}
    </style>
</head>

<body>
    <div  v-cloak id='app' class="recommendPage">
        <div class="swiper-container">
            <div class="swiper-wrapper">
                <div class="swiper-slide" v-for="(item, index) in tmList" :key="index">
                    <div class="box">
                        <van-divider class="qes-num"> {{ index + 1 }}/{{tmList.length}}</van-divider>
                        <p class="title">{{item.title}}</p>
                        <div class="anlist">
                            <ul>

								<li :class="{
						    	'success-active': item.userAnswer === subIndex,
								'error-active':item.userAnswer!==item.correct && item.userAnswer === subIndex}"
												v-for="(sub, subIndex) in item.answer" :key="sub.id" class="lis"
												@click="chechan(item,sub,  index,subIndex)">
									{{ sub }}
								 </li>
                            </ul>
                        </div>
                        <div v-if="isShowAnswer===index||item.userAnswer!==-1">
                            <div class="mar20">
                                正确答案: <span class="redcol"> {{ item.answer[item.correct] }}</span>
                            </div>
                            <div class="mar20 pa20">解析: {{ item.content }}</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
</body>
<script>
    const app = new Vue({
        el: "#app",
        data() {
            return {
                swiper: {},
                isShowAnswer: -1,// 控制是否显示解析
                isActive: -1,
                tmList: [
                    {
                        id: 1,
                        title: '1、1947年12月,毛泽东在《目前形势和我们的任务》中总结出十大军事原则,其核心是( )',
                        correct: 0,
                        answer: [
                            'A.集中优势兵力,各个歼灭敌人',
                            'B.诱敌深入,积极防御',
                            'C.多种作战形式,适时转变',
                            'D.避其主力,打其虚弱'
                        ],
                        userAnswer: -1,  
                        content: "毛泽东于1947年12月25日在中共中央召开的会议上所做《目前形势和我们的任务》的报告中正式提出十大军事原则。十大军事原则是一个有机的整体,其核心是强调集中优势兵力打歼灭战", 
                    },
                    {
                        id: 2,
                        title: '2、中国宋代哲学家朱熹提出“理在事先”,把“天理”说成是世界万物的本原。这是一种( )',
                        correct: 1,
                        answer: ['A.主观唯心主义观点', 'B.客观唯心主义观点', 'C.朴素唯物主义观点', 'D.形而上学唯物主义观点'],
                        userAnswer: -1,  
                        content: "主观唯心主义认为物质是某种主观精神的产物,客观唯心主义将物质归结为某种客观精神的产物。结合题干可得,“理在事先”这种“天理”观属于客观唯心主义。",
                    },
                    {
                        id: 3,
                        title: '3、毛泽东在《新民主主义论》中提出的新民主主义文化纲领是( )',
                        correct: 2,
                        answer: [
                            'A.为抗战服务',
                            'B.为工农兵服务',
                            'C.民族的、科学的、大众的文化',
                            'D.古为今用,洋为中用'
                        ],
                        userAnswer: -1, 
                        content: "新民主主义的文化就是“无产阶级领导的,人民大众的,反帝反封建的文化”。这种文化是无产阶级领导的民族的、科学的、大众的文化。",
                    },
					{
					    id: 4,
					    title: '4、下列选项中,强调外因在事物发展中起着重要作用的是( )',
					    correct: 2,
					    answer: [
					        'A.出淤泥而不染',
					        'B.威武不能屈,贫贱不能移',
							'C.近朱者赤,近墨者黑',
							'D.常在河边走,就是不湿鞋'
					    ],
					    userAnswer: -1, 
					    content: "在因果联系中,内因是事物变化的根据,外因是事物变化的条件。“近朱者赤,近墨者黑”强调的是外因在事物变化发展中的重要作用。",
					}
                ],
            }
        },
        methods: {
            chechan(v1, v2, index, index1) {
		      
                if (v1.userAnswer !== -1) return // 代表已经答过了
                this.isActive = index1//选中当前选项
                this.isShowAnswer = index //选完显示答案和解析
                 v1.userAnswer = index1;   //此处非常关键,已经改变了 tmList数组
                if (index1 === v1.correct) {
                    this.nextto();
                } 
                console.log("点击的答案" + v1, "正确答案" + `${v2}`, "第" + `${index + 1}` + "题", `点击了第${index + 1}题的第${index1 + 1}答案`);
           
				//判断最后一个  此判断只适用于最后一个题目的答案 和没一道题的 选项唯一   根据自己的业务判断最后一个题
				let clicklast = v1.content;
                let arrlast = this.tmList[this.tmList.length-1].content;
				if(clicklast==arrlast){
				       alert("恭喜你完成答题")
				}
				
            },

            nextto() {
                //获取当前索引
                let thisindex = this.swiper.activeIndex;
                this.swiper.slideTo(thisindex + 1, 1000, false);
            },
        },
        mounted() {
            let that = this;
            that.swiper = new Swiper('.swiper-container', {
                initialSlide: 0, //默认显示
		        autoplay:false,//等同于以下设置
                on: {
                    touchStart: function () {
                        // alert(this.activeIndex);//切换结束时,告诉我现在是第几个slide
                    },
                },
            })
        },
        created() {
             
        }
    });
</script>

</html>
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-30 12:28:21  更:2021-10-30 12:28:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/11 0:41:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码