第15篇:答题交互组件——Exam 与 SelectComponent 全解析
一、引言
答题交互是驾考应用最核心的用户交互场景。DriverLicenseExam 项目的Exam组件和SelectComponent组件共同实现了完整的答题交互体验,包括试题展示、选项选择、答案判断、答题卡、倒计时等。本文将深入解析这两个组件的实现。
二、Exam 组件架构
2.1 组件职责
Exam 组件是考试页面的核心容器,负责:
- 管理试题列表(Swiper 滑动切换)
- 展示倒计时(模拟考试)
- 管理答题卡浮层
- 处理模拟考试结束弹窗
2.2 组件接口
// components/exam/src/main/ets/components/Exam.ets@Entry@ComponentV2 export struct Exam {@Param@RequireappPathStack: NavPathStack;// 路由栈@Param@RequireexamManager: ExamManager;// 试卷数据@ParammockExamCall: (score: number) => void = (score: number) => {};// 模拟考试回调private examController: ExamController = ExamController.instance;@LocalremainTime: number =0;// 剩余时间@LocalisShowProblemListSheet: boolean = false;// 答题卡显示@LocalcurrentIndex: number =0;// 当前第几题@LocalisStop: boolean = false;// 暂停状态private readonly renderWindowSize: number =2;// 渲染窗口大小}三、答题交互流程
3.1 试题渲染
build(){Column(){// 模拟考试倒计时this.showRemainTime();// 试题列表(Swiper 滑动切换)Swiper(examController.swiperController){ForEach(this.examManager.examDetails, (item: ExamDetail,examIndex:number)=> {Column({space: 12 }){if(this.shouldRenderQuestion(examIndex)) { SelectComponent({item: item,changeCorrectNum: (isAdd: boolean) => {isAdd ? this.examManager.correctNumber++: this.examManager.correctNumber--;},}); } } }); } // ... 底部导航(答题卡、上一题、下一题) } }3.2 渲染窗口优化
// 只渲染当前题附近的题目,提高大题库性能privatereadonlyrenderWindowSize:number=2;shouldRenderQuestion(examIndex:number):boolean{returnMath.abs(examIndex -this.currentIndex) <=this.renderWindowSize; }四、模拟考试倒计时
4.1 倒计时实现
aboutToAppear(): void {this.currentIndex =this.examManager.currentQuestionId +1;if(this.examManager.timeLimit !==0) {this.remainTime =this.examManager.timeLimit *60; let showDialog: boolean =true; setInterval(() => {if(showDialog && !this.isStop) {if(this.remainTime >=1) {this.remainTime--; }else{ showDialog =false;this.isStop =true;this.examSubmitDialog.open(); } } },1000); } }4.2 时间格式化
@BuildershowRemainTime() {if(this.examManager.timeLimit!==0) {Row() {Image($r('app.media.ic_time')).width(16).height(16);Text(`${Math.floor(this.remainTime /60)}:${String(this.remainTime %60).padStart(2,'0')}`) .fontSize(14) .fontColor('#FF6B6B'); } } }五、答题卡实现
5.1 答题卡数据
// 生成答题卡数据getanswerCardData() {returnthis.examManager.examDetails.map((item, index) =>({index: index +1,status: item.isCorrect===undefined?'unanswered': item.isCorrect?'correct':'wrong',isCurrent: index ===this.currentIndex})); }5.2 答题卡交互
// 底部打开答题卡浮层Button('答题卡') .onClick(() => {this.isShowProblemListSheet =true; }) .bindSheet($$this.isShowProblemListSheet,this.answerCardSheet(), { height:400, title: { title:'答题卡'}, });六、总结
Exam 和 SelectComponent 组件的设计体现了 ArkUI 组件化的最佳实践:
- 职责分离:Exam 管理流程,SelectComponent 管理交互
- 性能优化:渲染窗口机制减少不必要的渲染
- 状态管理:@Local 管理内部状态,@Param 接收外部数据
- 用户体验:倒计时、答题卡、弹窗等交互细节
关键源码文件:
components/exam/src/main/ets/components/Exam.ets— 考试主组件components/exam/src/main/ets/components/SelectComponent.ets— 选择组件components/exam/src/main/ets/controller/ExamController.ets— 考试控制器