问卷调查怎么写?
前台的逻辑部分也就是在——单选和多选的实现以及存储上面
第一步:首先了解数据的基本类型、格式——大致如下(两个单选题目,一个多选题目):
state = {
choose_data: [
{
title_num:'1',
id: 1,
key: '1',
title: '【安全类】请选择您心目中的“职业形象达 人”',
title_type: 1,
choose_list: [
{
id: 1,
key: '1-1',
letter: 'A',
img: choose_pic,
content: '安全部-特勤-张XX',
},
{
id: 2,
key: '1-2',
letter: 'B',
img: choose_pic,
content: '安全部-特勤-赵XX',
}
]
},
{
title_num:'2',
id: 2,
key: '2',
title: '有安全意识的是',
title_type: 1,
choose_list: [
{
id: 1,
key: '1-1',
letter: 'A',
content: '我是选择一',
},
{
id: 2,
key: '1-2',
letter: 'B',
content: '我是选择2',
}
]
},
{
title_num:'3',
id: 3,
key: '3',
title: '是颜色的有',
title_type: 2,
choose_list: [
{
id: 1,
key: '1-1',
letter: 'A',
content: '我是选择一',
},
{
id: 2,
key: '1-2',
letter: 'B',
content: '我是选择2',
},
{
id: 3,
key: '1-3',
letter: 'C',
content: '我是选择2',
}
]
}
],
answer: [], //存储选择的答案(以数组包裹对象的方式来存储)
}
包括的内容:题目id(题目标题、单选还是多选、题号等),第二层是选项的内容(每个选项的id、内容等)
第二步 引入antd单选多选标签
import { Radio,Checkbox } from 'antd';
该情景下的单选多选框略有不同,所以需要利用选框组的形式来实现(为了确保每个题目的答案选择不会跟其他题目冲突):
所以还需要声明选框组的标签
const RadioGroup = Radio.Group;
const CheckboxGroup = Checkbox.Group;
第三步 页面的呈现方式
<ul className={styles.topic_list_box}>
{
data.map((item) => {
return (
<li key={item.id}>
<p><span className={styles.title_num}>{`${item.title_num}.`}</span>{item.title}<span className={styles.topic_type}>{item.title_type===1?'单选题':'多选题'}</span></p>
<ul className={styles.choose_list}>
{
item.title_type===1?
<RadioGroup name="radiogroup" onChange={this.change_radio.bind(this, item.id)}>
{
item.choose_list.length > 0 ?
item.choose_list.map((item1) => {
return (
<li key={item1.id}>
{item1.img ? <img src={item1.img} alt="choose_pic" /> : ''}
<div className={styles.content}>
<span>{`${item1.letter}.`}</span>
<Radio
value={item1.letter}
>{item1.content}</Radio>
</div>
</li>
)
}) : ''
}
</RadioGroup>:
<CheckboxGroup onChange={this.change_radio.bind(this, item.id,'checkbox')}>
{
item.choose_list.length > 0 ?
item.choose_list.map((item1) => {
return (
<li key={item1.id}>
{item1.img ? <img src={item1.img} alt="choose_pic" /> : ''}
<div className={styles.content}>
<span>{`${item1.letter}.`}</span>
<Checkbox
value={item1.letter}
>{item1.content}</Checkbox>
</div>
</li>
)
}) : ''
}
</CheckboxGroup>
}
</ul>
</li>
)
})
}
</ul>
基本逻辑:如果是单选题的话,按照单选的格式来渲染,否则按照复选的格式来渲染(都是一组的格式),因为这样才能保证每道题目都是独立的
事件:onChange()
因为单选和多选事件中的参数代表的是不同的意思,所以需要区分一下
//选择
change_radio(title_id, e,str) {
const answer_current = this.state.answer; //原本state数组中存储的数据
const answer_new = { title: title_id, choose_id: e==='checkbox'?str:e.target.value} //最新原则的题目以及对应的答案
answer_current.map((item) => {
if (item.title === title_id) { //如果原来的数组中题号存在和最新的一样的,则要剔除
answer_current.splice(answer_current.indexOf(item), 1)
}
})
//把最新的答案拼接到原来的数组中
this.setState({
answer: this.state.answer.concat(answer_new)
})
}
事件逻辑:
state中answer代表的是现有的答案(即在事件中重新声明之后的answer_current ),变量answer_new 代表的是用户最新选择的题目以及对应的答案,也就是说需要把新的答案存储到answer中之外,还要判断answer中是否有同样的题目的答案,有的话则需要删除掉。
至于==answer_new ==
choose_id要根据e来判定是因为,单选事件和多选事件中的参数不一样,
如果是单选e代表的是事件对象,str是undefined,
如果是多选,e代表的是我们传递进去的参数‘checkbox’,str则代表我选中的答案,所以是这样一个格式
万般滋味,都是生活。公众号求关注哦!