背景
最近在用 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>
内容版权声明:除非注明,否则皆为本站原创文章。
