背景
最近在用 Vue 重构一个历史项目,一个考试系统,题目量很大,所以核心组件的性能成为了关注点。先来两张图看下最核心的组件 Paper 的样式。
从图中来看,分为答题区与选择面板区。
稍微对交互逻辑进行下拆解:
- 答题模式与学习模式可以相互切换,控制正确答案显隐。
- 单选与判断题直接点击就记录答案正确性,多选是选择答案之后点击确定才能记录正确性。
- 选择面板则是记录做过的题目的情况,分为六种状态(未做过的,未做过且当前选择的,做错的,做错的且当前选择的,做对的,做对的且当前选择的),用不同的样式去区别。
- 点击选择面板,答题区能切到对应的题号。
基于以上考虑,我觉得我必须有三个响应式的数据:
currentIndex
: 当前选中题目的序号。questions
:所有题目的信息,是个数组,里面维护了每道题的问题、选项、正确与否等信息。cardData
:题目分组的信息,也是个数组,按章节名称对不同的题目进行了分类。
数组每一项数据结构如下:
currentIndex = 0 // 用来标记当前选中题目的索引 questions = [{ secId: 1, // 所属章节的 id tid: 1, // 题目 id content: '题目内容' // 题目描述 type: 1, // 题型,1 ~ 3 (单选,多选,判断) options: ['选项1', '选项2', '选项3', '选项4',] // 每个选项的描述 choose: [1, 2, 4], // 多选——记录用户未提交前的选项 done: true, // 标记当前题目是否已做 answerIsTrue: undefined // 标记当前题目的正确与否 }] cardData = [{ startIndex: 0, // 用来记录循环该分组数据的起始索引,这个值等于前面数据的长度累加。 secName: '章节名称', secId: '章节id', tids: [1, 2, 3, 11] // 该章节下面的所有题目的 id }]
由于题目可以左右滑动切换,所以我每次从 questions
取了三个数据去渲染,用的是 cube-ui 的 Slide 组件,只要自己根据 this.currentIndex 结合 computed 特性去动态的切割三个数据就行。
这一切都显得很美好,尤其是即将结束了一个历史项目的核心组件的编写之前,心情特别的舒畅。
然而转折点出现在了渲染选择面板样式这一步
代码逻辑很简单,但是发生了让我懵逼的事情。
<div class="card-content"> <div class="block" v-for="item in cardData" :key="item.secName"> <div class="sub-title">{{item.secName}}</div> <div class="group"> <span @click="cardClick(index + item.startIndex)" class="item" :class="getItemClass(index + item.startIndex)" v-for="(subItem, index) in item.secTids" :key="subItem">{{index + item.startIndex + 1}}</span> </div> </div> </div>
内容版权声明:除非注明,否则皆为本站原创文章。