十分钟手把手教你设计简单易用的组件级考试题(单选多选填空图片),建议收藏
Posted webmote
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了十分钟手把手教你设计简单易用的组件级考试题(单选多选填空图片),建议收藏相关的知识,希望对你有一定的参考价值。
对于学生党来说,最常见的莫过于试卷考试题,调查问卷测试题等等,有没有一款论文是管理考试题库的?对于新手刚入门的同学来说,仔细看本文,保证你看完后可以自己手撸代码。
1、试卷题
试卷题型有很多种,常见的有单选、多选、填空、图片题等等,例如下图的问卷调查题。
2 题型组件定义
这么多题型,其界面和操作形式各有异同,因此我们可以简单的按照题型进行设计组件。
如下组织形式,我们先建立WQuestionItem 文件夹,然后添加各型号的题型组件:
- ImageSingleItem : 图片单选题
- MultiItem: 多选题
- SingleItem: 单选题
- TextItem: 填空题
- NumItem: 数字题
- …
2.1 设计单选题型组件
万事开头难,如果我们能顺利的设计好单选题型,那么多选题型可能仅仅是选择和结果不同而已。
因此在设计单选题组件时,我们需要费点力气。
好了,看看设计的组件类图。
这里单选题型组件作为一个响应输入,返回结果的组件,最最适合实现其v-model
的双向绑定行为。我们都试过ElementUI的各个vue组件,那个设计的溜啊,这里我们也借鉴以下。
vue官方解释:
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。利用model 选项可以用来避免这样的冲突。
2.1.1 模板设计
我们采用ElementUI来作为主要的输出UI。在布局上使用el-card
,刚好把试题的标题放在header区,把选项放在数据区。
<template>
<div>
<el-card class="box-card" :shadow="shadow" :body-style="bodyStyle">
<div slot="header" class="clearfix">
<el-row type="flex" justify="space-between">
<el-col :span="20">
<h3> question.title </h3>
</el-col>
<el-col :span="4" style="width:300px;text-align:right;">
</el-col>
</el-row>
</div>
<el-form
ref="form"
:model="answer"
label-width="20px"
label-position="top"
size="medium"
class="question"
>
<template>
<el-form-item>
<el-radio-group ref="rg" :value="answer.content" @input="handleInput">
<el-col
v-for="(item, index) in question.items"
:key="index"
:class="className"
style="margin-bottom:20px;"
@mouseover.native="hover($event)"
@mouseout.native="removeClass($event)"
>
<el-radio :label="item.index"> item.content </el-radio>
</el-col>
</el-radio-group>
</el-form-item>
</template>
</el-form>
</el-card>
</div>
</template>
这里使用
@mouseover.native="hover($event)" @mouseout.native="removeClass($event)"
完成鼠标滑过选项的效果。
2.1.2 组件代码实现1
可以预见的是,组件内必然有部分代码需要公用,因此我们设计了混合类,来复用功能。
export const CommonItem =
data()
return
className: '',
activeName: 0,
,
created()
// console.log('这是混入对象的created')
,
methods:
hover(event)
event.currentTarget.className = 'bold'
,
removeClass(event)
event.currentTarget.className = ''
,
,
computed:
shadow()
return this.question.child ? 'never' : 'always'
,
bodyStyle()
return this.question.child ? 'min-height:320px ;background-color: transparent'
: 'min-height:320px ;background: -webkit-linear-gradient(top,rgba(234, 240, 184, 0.212),rgba(224, 221, 172, 0.507),rgb(234, 240, 184)) no-repeat;'
,
,
2.1.3 组件代码实现2
混合类作为基础打底,也可以随时把公用代码提取到混合类里。
现在该到了单选组件实现的代码了。
// 引用混合类
import CommonItem from './mixins'
export default
name: 'SingleItem',
mixins: [CommonItem],
//重定义model名,我们接收到answer
model:
prop: 'answer',
event: 'input'
,
props:
// 题
question:
type: Object,
required: true,
default: () =>
return
,
answer:
type: Object
,
,
再设计方法,主要处理输入事件。
注意:选项的值放在 answer.content
。然后组织好值后,触发组件的时间input this.$emit('input', rtn)
。
methods:
handleInput(value)
var rtn =
...this.answer,
content: value,
state: value >= 0
console.log('single handleInput:', rtn)
this.$emit('input', rtn)
,
handleKeyDown(e)
// console.log('key:',e.keyCode)
if (e.keyCode > 48 && e.keyCode <= 57)
// 1 答案0
var index = (e.keyCode - 49)
if (this.question.items.length > index && index >= 0)
var ans = index.toString()
this.handleInput(ans)
e.preventDefault()
,
handleKeyUp(e)
,
2.2 填空题组件
既然已经搞定了单项选择题,那么我们就开始填空题组件,应为它比较简单,柿子先从软的捏。
复制单选择题组件,修改为TextItem.vue.
替换模板中的el-form
:
<el-form
ref="form"
:model="answer"
label-width="20px"
label-position="top"
size="medium"
class="question"
>
<template>
<el-form-item label="">
<el-input
type="textarea"
:value="textVal"
@input="handleInput"
/>
</el-form-item>
</template>
</el-form>
2.2.1 定义组件代码
增加data:
data()
return
textVal: Array.isArray(this.answer.content) ? '' : this.answer.content
,
2.2.2 处理输入
handleInput(value)
var rtn =
...this.answer,
content: value,
state: value.length > 0
console.log('text handleInput:', rtn)
this.$emit('input', rtn)
,
2.3 多选题组件
利用Ctrl+C、Ctrl+V大法,修改el-form
代码:
<el-form
ref="form"
:model="answer"
label-width="20px"
label-position="top"
size="medium"
class="question"
>
<template>
<el-form-item>
<el-checkbox-group :value="answer.content" @input="handleInput">
<el-col
v-for="(item, index) in question.items"
:key="index"
style="margin-bottom: 20px"
@mouseover.native="hover($event)"
@mouseout.native="removeClass($event)"
>
<el-checkbox
:label="item.index"
>【 item.index 】、 item.content </el-checkbox>
</el-col>
</el-checkbox-group>
</el-form-item>
</template>
</el-form>
这里仅需要处理输入事件即可,我们返回一个数组作为多选题的答案。
handleInput(value)
var rtn =
...this.answer,
content: [],
state: value.length > 0
var arr = value || []
arr.forEach(item =>
if (item != '' && item != '-1')
rtn.content.push(item)
)
console.log('multi handleInput:', rtn)
this.$emit('input', rtn)
2.4 图片题
图片题是单选题的变种,只是标题是图片而已,因此我们只需要复制一个单选题,修改标题。
<el-image style="width: 381px; height: 411px" :src="question.title" lazy />
哈哈,搞定了。
3. 构建父组件
题型组件已经构建完成了,那我们需要一个父组件封装适合各种题型的组件。
这个组合采用题型进行判断:
<template>
<div>
<template v-if="question.type=='single'">
<single-item
v-model="answerVal"
:question="question"
@input="handleInput"
/>
</template>
<template v-else-if="question.type=='multi'">
<multi-item
v-model="answerVal"
:question="question"
@input="handleInput"
/>
</template>
<template v-else-if="question.type=='image'">
<image-single-item
v-model="answerVal"
:question="question"
@input="handleInput"
/>
</template>
<template v-else-if="question.type=='text'">
<text-item
v-model="answerVal"
:question="question"
@input="handleInput"
/>
</template>
<template v-else>
dont setup question type
</template>
</div>
</template>
实现代码如下:
export default
name: 'WQuestionItem',
components: SingleItem, MultiItem, TextItem, ImageSingleItem ,
model:
prop: 'answer',
event: 'input'
,
props:
question:
type: Object,
required: true,
default: () =>
return
,
answer:
type: Object
,
,
data()
return
answerVal: JSON.parse(JSON.stringify(this.answer))
,
computed:
,
methods:
handleInput(val)
console.log('wquestionItem', val)
this.$emit('input', val)
运行下效果~~~~
4 小结
利用vue 的组件,我们实现了单选、多选、填空、图片等题型的设计,如果你还有更多的需求,可以在此基础上方便的扩展。
关注我,不迷路;一块学习vue,一块进步!
以上是关于十分钟手把手教你设计简单易用的组件级考试题(单选多选填空图片),建议收藏的主要内容,如果未能解决你的问题,请参考以下文章
iOS——UITableView单选模式,多选模式,单选多选混合模式
手把手教你由TensorFlow上手PyTorch(附代码)