嘿,最近我搞了个Java刷题的小程序,用Vue写的,界面和功能都还挺完整的。今天就来跟大家聊聊这个小程序是怎么实现的,代码里都藏着哪些小细节。

先看整体结构,我把整个页面分成了几个大块:顶部导航栏、题目内容区、底部按钮栏,还有一个完成后的弹窗。这种布局应该挺符合大家做题库类应用的习惯吧?

图片

顶部导航栏

<view class="navbar"><text class="nav-title">Java刷题</text><text class="nav-progress">{{ currentIndex + 1 }}/{{ totalCount }}</text>
</view>

这块很简单,左边是标题,右边显示当前进度,比如"3/10"这种。用currentIndex + 1是因为数组索引是从0开始的,加1才符合我们平时的计数习惯。

题目内容区

这部分是核心,我分了题干、选项列表和答案解析三个部分。

首先是题干:

<view class="question-content"><text class="question-title">题目 {{ currentIndex + 1 }}:</text><text class="question-text">{{ currentQuestion.questionContent }}</text>
</view>

这里用了v-if="currentQuestion"来确保数据加载完成后才显示,避免页面闪烁。

然后是选项列表,这块有点意思:

<view class="options-list"><view class="option-item" v-for="(option, idx) in parsedOptions" :key="idx":class="{ 'selected': selectedIndex === idx,'correct': showExplanation && isCorrectOption(idx),'incorrect': showExplanation && selectedIndex === idx && !isCorrectOption(idx)}"@click="handleSelectOption(idx)"><text class="option-letter">{{ String.fromCharCode(65 + idx) }}</text><text class="option-text">{{ option }}</text></view>
</view>

我用了v-for来循环渲染选项,parsedOptions是处理过的选项数组。这里有个小技巧,选项字母A、B、C、D是通过String.fromCharCode(65 + idx)生成的,65对应的就是字母A的ASCII码,这样就不用手动写每个选项的字母了。

样式方面,我用了动态class:

  • 选中状态:selected

  • 正确答案:correct类(只有在显示解析时才生效)

  • 错误答案:incorrect类(选中的答案不对时才显示)

这样用户选完答案提交后,就能清楚地看到自己选的对不对,正确答案是哪个。

图片

接下来是答案解析,只有提交答案后才会显示:

<view class="explanation" v-if="showExplanation"><text class="explanation-title">解析:</text><text class="explanation-content">{{ currentQuestion.answerExplanation }}</text>
</view>

底部导航按钮

<view class="bottom-bar"><button class="btn-prev" @click="prevQuestion" :disabled="currentIndex === 0">上一题</button><button class="btn-next" @click="nextQuestion" :disabled="!hasSelected && currentIndex === totalCount - 1">{{ currentIndex === totalCount - 1 ? '完成练习' : (hasSelected ? '下一题' : '请选择答案') }}</button>
</view>

这里的按钮文本会根据当前状态动态变化:

  • 如果是最后一题,显示"完成练习"

  • 否则,如果已经选了答案,显示"下一题"

  • 还没选答案的话,显示"请选择答案"

disabled属性也做了处理,第一题时上一题按钮禁用,最后一题没选答案时,完成按钮也会禁用,防止用户跳过题目。

完成弹窗

<view class="result-popup" v-if="showResult"><view class="popup-content"><text class="popup-title">练习完成!</text><text class="popup-score">得分: {{ correctCount }}/{{ totalCount }}</text><button class="popup-button" @click="restart">重新开始</button><button class="popup-button" style="margin-top: 10px;" @click="restart2">再战错题</button></view>
</view>

全部做完后会弹出这个弹窗,显示得分,还有两个按钮:重新开始和再战错题。这个再战错题功能我觉得还挺实用的,能针对性地巩固薄弱点。

图片

脚本部分

接下来看看逻辑实现,我用的是Vue 3的setup语法。

首先定义了一些状态变量:

const currentIndex = ref(0) // 当前题目索引
const currentQuestion = ref(null) // 当前题目数据
const selectedIndex = ref(-1) // 选中的选项索引,-1表示未选择
const showExplanation = ref(false) // 是否显示解析
const totalCount = ref(0) // 总题数
const correctCount = ref(0) // 做对的题数
const showResult = ref(false) // 是否显示结果弹窗

然后是一些计算属性:

// 解析选项,把字符串分割成数组
const parsedOptions = computed(() => {if (!currentQuestion.value?.options) return []return currentQuestion.value.options.split('\n').filter(option => option.trim()).map(option => option.replace(/^[A-Z]\./, '').trim())
})// 是否已选择答案
const hasSelected = computed(() => selectedIndex.value !== -1)

parsedOptions会把后端返回的选项字符串(可能是用换行分隔的)转换成数组,还会去掉每个选项前面的A.、B.这种前缀,让显示更干净。

处理选择选项的方法:

const handleSelectOption = (idx) => {if (showExplanation.value) return // 已显示解析,禁止修改selectedIndex.value = idx
}

这里加了个判断,如果已经显示解析了,就不能再改答案了,避免用户反复修改。

上一题和下一题的逻辑:

const prevQuestion = () => {
if (currentIndex.value > 0) {currentIndex.value--loadCurrentQuestion()}
}const nextQuestion = () => {
if (!hasSelected.value) return// 未选择答案// 检查答案是否正确
if (!showExplanation.value) {const userAnswer = String.fromCharCode(65 + selectedIndex.value)if (userAnswer === currentQuestion.value.correctAnswer) {correctCount.value++reportCorrect(currentQuestion.value.id); // 上报正确答案} else {reportIncorrect(currentQuestion.value.id); // 上报错误答案}showExplanation.value = truereturn}// 跳转到下一题
if (currentIndex.value < totalCount.value - 1) {currentIndex.value++loadCurrentQuestion()} else {// 完成所有题目showResult.value = true}
}

下一题的逻辑稍微复杂点:

  1. 首先检查是否已经选择答案,如果没有就直接返回

  2. 如果还没显示解析,就先判断答案是否正确,更新正确题数,然后显示解析

  3. 如果已经显示解析了,就跳到下一题,或者如果是最后一题,就显示结果弹窗

加载当前题目的方法:

const loadCurrentQuestion = () => {currentQuestion.value = questionData.value[currentIndex.value] selectedIndex.value = -1 // 重置选择状态showExplanation.value = false // 隐藏解析
}

每次切换题目时,都会重置选择状态和解析显示状态。

重新开始和再战错题的功能:

const restart = () => {currentIndex.value = 0correctCount.value = 0showResult.value = falseuni.redirectTo({url:"/pages/aaa/aaa"})
}const restart2 = async () => {
let resData = await expendPoint('java刷题',20)
if (resData.code !== 200) {uni.showModal({title: '提示',content: resData.message,});return}showResult.value = falsecurrentIndex.value = 0correctCount.value = 0uni.showLoading({title:"加载中",mask: true});
const tms = await selectError(); // 获取错题uni.hideLoading();questionData.value = tms;totalCount.value = tms.length;loadCurrentQuestion()
}

这里的expendPoint是个能量消耗的接口,可能是我这个小程序里的一个积分系统,做错题练习需要消耗20点能量。

最后是页面加载时的初始化:

onMounted(async () => {
let resData = await expendPoint('java刷题',20)
if (resData.code !== 200) {uni.showModal({title: '提示',content: resData.message,});return}uni.showLoading({title:"加载中",mask: true});
const tms = await randomTm(); // 获取随机题目uni.hideLoading();questionData.value = tms;totalCount.value = tms.length;loadCurrentQuestion()
})

页面一加载就会调用接口获取题目数据,同时显示加载中提示,让用户知道正在加载。

样式部分

样式我用了scoped属性,确保不会污染其他组件。主要处理了各种状态的显示效果,比如选中、正确、错误的样式区分,还有弹窗的遮罩效果等。

总的来说,这个小程序虽然简单,但功能还挺完整的,用户体验上也做了不少细节处理。比如:

  • 清晰的进度显示

  • 直观的答案反馈(正确/错误)

  • 详细的解析说明

  • 错题重练功能

  • 合理的按钮状态控制

代码结构也比较清晰,把UI和逻辑分离,方便后续维护和扩展。如果想加新功能,比如收藏题目、难度筛选什么的,也很容易在这个基础上扩展。

大家觉得这个小程序怎么样?有什么可以改进的地方欢迎一起讨论~

点击下方链接,即可体验~

速用百宝箱https://mp.weixin.qq.com/s?__biz=MzI1ODI1ODkzMA==&mid=2247497389&idx=1&sn=dd67cedd437a01b3f06507d38650ffde&chksm=ebe1b5699d11eaf0db4a06891d66a85e81642d24ac5f209576907e695aa84080485fa0af6136&scene=126&sessionid=1753317024&subscene=91&clicktime=1753317025&enterid=1753317025&key=daf9bdc5abc4e8d0431ce024e74393f3d4d7363a48a9149b474f3b8cf23986d4b35229bab8d5ea130bb8d6cac53a81552b00c36509a1417c0cd156bcc51f1eab9f4256a30fa6f38a00fce6ebe4c6687ac0a6951f6cece7c99ac7a3ad0802fec5444a13ea0b7ec6943b769291a6397feb6cb7ce96bb4dcd0ea4c3a20b94274060&ascene=0&uin=NDAwODI4MTc2&devicetype=Windows+11+x64&version=63090c37&lang=zh_CN&countrycode=CN&exportkey=n_ChQIAhIQC%2Byv%2BJhP3dcGtQjVPBMVaRLmAQIE97dBBAEAAAAAAONbCcPymDMAAAAOpnltbLcz9gKNyK89dVj0mId9lGY7cgnRR9uMjFqtA85HhyhxR%2F8MkxC519%2BAAh5oQXtwcxPqtbYuMxU9JG0jLZYRcQ6v6JjRHJNp8ys0DuFDth01%2Fp3jjmgfq9HvxRpISFTGcQeWwa5V638C1okgLeuZSo%2BIQ7HhM0cM1JDjoeoCj4RS4DVLDLeupELVNXBvlf7OkIUXSv6UqorKMIEzGKrpeQA%2BBPGRVfR3u%2BhoINPcohS22vIVXyOvaMNODUGi04FFuwOSZzsrHtd3Mkxp&acctmode=0&pass_ticket=blZdPvi3Lplm9v5ei2FR0KEPOc%2FjdsNpEJy8DRmJcCqu5pYRRJMo5GEgEjyl5FKH&wx_header=1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915929.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915929.shtml
英文地址,请注明出处:http://en.pswp.cn/news/915929.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式开发学习———Linux环境下数据结构学习(三)

单向循环链表单向循环链表是一种特殊的单向链表&#xff0c;尾节点的指针指向头节点&#xff0c;形成一个闭环。适用于需要循环访问的场景&#xff0c;如轮询调度。结构特点&#xff1a;每个节点包含数据域和指向下一个节点的指针&#xff0c;尾节点的指针指向头节点而非空值。…

【华为机试】684. 冗余连接

文章目录684. 冗余连接描述示例 1示例 2提示解题思路核心分析问题转化算法选择策略1. 并查集 (Union-Find) - 推荐2. 深度优先搜索 (DFS)3. 拓扑排序算法实现详解方法一&#xff1a;并查集 (Union-Find)方法二&#xff1a;深度优先搜索 (DFS)数学证明并查集算法正确性证明时间复…

Ⅹ—6.计算机二级综合题7---10套

目录 第7套 【填空题】 【修改题】 【设计题】 第8套 【填空题】 【修改题】 【设计题】 第9套 【填空题】 【修改题】 【设计题】 第10套 【填空题】 【修改题】 【设计题】 第7套 【填空题】 题目要求:给定程序中,函数fun的功能是:将形参s所指字符串中所…

【三桥君】大语言模型计算成本高,MoE如何有效降低成本?

​ 你好&#xff0c;我是 ✨三桥君✨ &#x1f4cc;本文介绍&#x1f4cc; >> 一、引言 在AI技术飞速发展的当下&#xff0c;大语言模型&#xff08;LLM&#xff09;的参数规模不断增长&#xff0c;但随之而来的计算成本问题也日益凸显。如何在保持高效推理能力的同时扩…

Python游戏开发利器:Pygame从入门到实战全解析

引言 Pygame是Python中最受欢迎的2D游戏开发库之一&#xff0c;基于SDL&#xff08;Simple DirectMedia Layer&#xff09;构建&#xff0c;支持图形渲染、音效处理、事件响应等核心功能。无论是开发简单的休闲游戏&#xff0c;还是复杂的交互式应用&#xff0c;Pygame都能提供…

行为型模式-协作与交互机制

行为型模式聚焦于对象间的行为交互&#xff0c;通过规范对象协作方式提升系统的灵活性与可扩展性。在分布式系统中&#xff0c;由于多节点异步通信、网络不可靠性及状态一致性挑战&#xff0c;行为型模式需针对分布式特性进行适应性设计。本文从观察者、策略、命令、责任链、状…

spring boot 整合 Spring Cloud、Kafka 和 MyBatis菜鸟教程

环境准备确保项目中已引入 Spring Boot、Spring Cloud、Kafka 和 MyBatis 的依赖。以下是一个典型的 Maven 依赖配置&#xff1a;<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artif…

20 BTLO 蓝队靶场 Sticky Situation 解题记录

难度&#xff1a;5/10考察技能: Windows admin, Autopsy 使用场景&#xff1a;分析USB设备使用情况Autopsy使用注意&#xff1a;用管理员打开&#xff0c;在实际分析时注意先复制一个镜像文件&#xff0c;保存好原文件常用的Windows USB 取证的位置:Windows XP:Registry Key: U…

安装及配置Go语言开发环境与VSCode集成指南

安装Go语言开发 安装Go语言开发环境是第一步。访问Go官网&#xff0c;下载适合操作系统的安装包&#xff0c;如果进不去可以访问Go官方镜像站。 根据自己的系统选择对应的安装包&#xff0c;我这边是Windows系统就点击安装第一个即可。 点击下一步即可。 验证安装是否成功可以…

专题:2025微短剧行业生态构建与跨界融合研究报告|附100+份报告PDF汇总下载

原文链接&#xff1a; https://tecdat.cn/?p43384 分析师&#xff1a;Boyu Wang 在此对 Boyu Wang 对本文所作的贡献表示诚挚感谢&#xff0c;他在武汉大学完成了数据科学与大数据技术专业的学习。擅长 R 语言、Python、机器学习、数据可视化。 中国短视频行业在经历爆发式增…

配置NGINX

Nginx环境配置与前端VUE部署安装nginx&#xff1a;命令sudo yum update && sudo yum install nginx部署:拷贝前端到目录/home/publish/idasweb/下修改nginx配置&#xff1a;进入到/etc/nginx目录下&#xff0c;修改nginx.conf中user www-data为user root&#xff0c;不…

MySQL深度理解-MySQL索引优化

1.Order by与Group by优化1.1Case1employees表中建立了name&#xff0c;position和age索引&#xff0c;并且使用了order by age进行排序操作&#xff1a;EXPLAIN SELECT * FROM employees WHERE name LiLei and position dev order by age最终explain的结果发现使用了idx_nam…

「Linux命令基础」用户和用户组实训

用户与用户组关系管理 在Linux系统中,用户和用户组的关系就像班级里的学生和小组。一个用户可以同时属于多个组,这种灵活的成员关系为权限管理提供了便利。创建用户时,系统会自动生成一个与用户同名的主组,这个组会成为用户创建文件时的默认属组。 理解用户和用户组的关系…

Https以及CA证书

目录 1. 什么是 HTTPS 通信机制流程 证书验证过程 CA证书 浏览器如何校验证书合法性呢&#xff1f; 1. 什么是 HTTPS HTTP 加上加密处理和认证以及完整性保护后即是 HTTPS。 它是为了解决 HTTP 存在的安全性问题&#xff0c;而衍生的协议&#xff0c;那使用 HTTP 的缺点有…

数字图像处理(四:图像如果当作矩阵,那加减乘除处理了矩阵,那图像咋变):从LED冬奥会、奥运会及春晚等等大屏,到手机小屏,快来挖一挖里面都有什么

数字图像处理&#xff08;四&#xff09;三、&#xff08;准备工作&#xff1a;玩具咋玩&#xff09;图像以矩阵形式存储&#xff0c;那矩阵一变、图像立刻跟着变&#xff1f;原图发挥了钞能力之后的图上述代码包含 10 个图像处理实验&#xff0c;每个实验会生成对应处理后的图…

SpringBoot航空订票系统的设计与实现

文章目录前言详细视频演示具体实现截图后端框架SpringBoot持久层框架Hibernate成功系统案例&#xff1a;代码参考数据库源码获取前言 博主介绍:CSDN特邀作者、985高校计算机专业毕业、现任某互联网大厂高级全栈开发工程师、Gitee/掘金/华为云/阿里云/GitHub等平台持续输出高质…

2025年PostgreSQL 详细安装教程(windows)

前言 PostgreSQL 是一个功能强大的开源关系型数据库管理系统(ORDBMS)&#xff0c;以下是对它的全面介绍&#xff1a; 基本概况 名称&#xff1a;通常简称为 "Postgres" 类型&#xff1a;对象-关系型数据库管理系统 许可&#xff1a;开源&#xff0c;采用类MIT许可…

Java日志按天切分方法

使用 Logrotate&#xff08;推荐&#xff09;Logrotate 是 Linux 系统自带的日志管理工具&#xff0c;支持自动切割、压缩和删除旧日志。步骤&#xff1a;创建 Logrotate 配置文件在 /etc/logrotate.d/ 下新建配置文件&#xff08;如 java-app&#xff09;&#xff1a;sudo nan…

进阶向:基于Python的本地文件内容搜索工具

概述 大家好&#xff01;今天我们将一起学习如何用Python创建一个简单但强大的本地文件内容搜索工具。这个工具特别适合处理大量文本文件时的快速检索需求。 为什么要学习这个工具 如果你刚接触编程&#xff0c;完全不用担心&#xff01;我会从零开始讲解&#xff0c;确保每…

多模态AI的可解释性

多模态AI的可解释性挑战 在深入探讨解决方案之前&#xff0c;首先需要精确地定义问题。多模态模型因其固有的复杂性&#xff0c;其内部决策过程对于人类观察者而言是不透明的。 模态融合机制 (Modal Fusion Mechanism)&#xff1a;模型必须将来自不同来源&#xff08;如图像和文…