如何实现这样一个布局?
要求是这样的(目前的话换行单选多选判断换行展示已经处理完了):
但是现在有个问题就是选项的个数问题,选项最多是9个(也就是从A~I),最少是3~4个(判断的选项就是两个,但是若遇到判断就换行了,倒是不用太操心),选项个数不固定每题的宽度就不固定,宽度不固定列数就不固定,列数有影响到了行数,但又要求每列得对齐。
大致就是:
1.选项个数不固定
2.支持横排、竖排的切换
3.每列得对齐
所以想问问各位怎么实现这个需求?
数据:
list:[{
title: '1.单选题(8分)',
idProp: 'questionId',
code: 'single_choice',
choices: [
{ identifier: 'A', content: '茂陵刘郎秋风客,夜闻马嘶晓无迹' },
{ identifier: 'B', content: '画栏桂树悬秋香,三十六宫土花碧' },
{ identifier: 'C', content: '魏官牵车指千里,东关酸风射眸子' },
{ identifier: 'D', content: '空将汉月出宫门,忆君清泪如铅水' },
{ identifier: 'E', content: '空将汉月出宫门,忆君清泪如铅水' },
{ identifier: 'F', content: '空将汉月出宫门,忆君清泪如铅水' },
{ identifier: 'G', content: '空将汉月出宫门,忆君清泪如铅水' },
{ identifier: 'H', content: '空将汉月出宫门,忆君清泪如铅水' },
{ identifier: 'I', content: '空将汉月出宫门,忆君清泪如铅水' },
],
},
{
title: '2.单选题(8分)',
idProp: 'questionId',
code: 'single_choice',
choices: [
{ identifier: 'A', content: '茂陵刘郎秋风客,夜闻马嘶晓无迹' },
{ identifier: 'B', content: '画栏桂树悬秋香,三十六宫土花碧' },
{ identifier: 'C', content: '魏官牵车指千里,东关酸风射眸子' },
{ identifier: 'D', content: '空将汉月出宫门,忆君清泪如铅水' },
],
},
{
title: '3.单选题(8分)',
idProp: 'questionId',
code: 'single_choice',
choices: [
{ identifier: 'A', content: '茂陵刘郎秋风客,夜闻马嘶晓无迹' },
{ identifier: 'B', content: '画栏桂树悬秋香,三十六宫土花碧' },
{ identifier: 'C', content: '魏官牵车指千里,东关酸风射眸子' },
{ identifier: 'D', content: '空将汉月出宫门,忆君清泪如铅水' },
],
},
{
title: '4.单选题(8分)',
idProp: 'questionId',
code: 'single_choice',
choices: [
{ identifier: 'A', content: '茂陵刘郎秋风客,夜闻马嘶晓无迹' },
{ identifier: 'B', content: '画栏桂树悬秋香,三十六宫土花碧' },
{ identifier: 'C', content: '魏官牵车指千里,东关酸风射眸子' },
{ identifier: 'D', content: '空将汉月出宫门,忆君清泪如铅水' },
{ identifier: 'E', content: '茂陵刘郎秋风客,夜闻马嘶晓无迹' },
{ identifier: 'F', content: '画栏桂树悬秋香,三十六宫土花碧' },
{ identifier: 'G', content: '魏官牵车指千里,东关酸风射眸子' },
{ identifier: 'H', content: '空将汉月出宫门,忆君清泪如铅水' },
{ identifier: 'I', content: '空将汉月出宫门,忆君清泪如铅水' },
],
},]
vue组件代码:
<!-- * @Description: 选择题(单选、多选)、判断题
-->
<template>
<div
:class="[
'ac-sweep__choice',
showBorder && 'is-border',
isShowBorderBottom && 'is-border-bottom',
]"
>
<template v-if="Array.isArray(listData)">
<div v-for="(item, index) in listData" :key="index">
<ul :class="['ac-sweep__choice-box']">
<li
v-for="(_item, _index) in item"
:key="`${index}_${_index}`"
class="ac-sweep__choice-each"
>
{{ getBeforeChinese(_item.title) }}
<div class="ac-sweep__choice-item">
<span
v-for="(__item, __index) in _item.choices"
:key="`${index}_${_index}_${__index}`"
class="ac-sweep__choice-option"
>
{{ __item.identifier }}
</span>
</div>
</li>
</ul>
</div>
</template>
<template v-else>
<ul class="ac-sweep__choice-box">
<li>
{{ getBeforeChinese(list.title) }}
<div class="ac-sweep__choice-item">
<span
v-for="(_item, _index) in list.choices"
:key="_index"
class="ac-sweep__choice-option"
>
{{ _item.identifier }}
</span>
</div>
</li>
</ul>
</template>
</div>
</template>
<script>
export default {
name: 'AcSweepChoice',
components: {},
props: {
list: {
// 此处的类型为什么不统一?原因还是<ac-card>组件中transformTree函数所致,Array类型说明是连续的单选多选判断,Object类型说明这是个单个的单选、多选、判断
type: [Array, Object],
},
// 是否展示边框
showBorder: {
type: Boolean,
default: true,
},
// 是否展示下边框
isShowBorderBottom: {
type: Boolean,
default: false,
},
},
computed: {
layout() {
return this.$store.getters['AC/layout']
},
},
watch: {},
mounted() {
this.convertTree(this.list)
},
data() {
return {
listData: null,
}
},
methods: {
getBeforeChinese(str) {
const chineseReg = /[\u4e00-\u9fa5]/ // 匹配汉字的正则表达式
if (str) {
const index = str.search(chineseReg) // 查找第一个汉字的位置
if (index === -1) {
return str // 如果没有汉字,则返回原字符串
} else {
return str.slice(0, index) // 截取汉字之前的内容
}
}
},
/**
* @method convertTree
* @param questions
* @Description 此处承接<ac-card>组件中transformTree函数,之前在<ac-card>的transformTree函数中处理了将连续的单选多选判断放到一个数组中,那么下方的函数就是处理是否是连续的单选、多选或是判断了(这里的话如果是单独的单选、多选或是判断,是自身单独一个数组)。
*/
convertTree(questions) {
if (Array.isArray(questions)) {
// 创建空数组用于存储分组后的题目
const groupedQuestions = []
// 遍历题目数组
for (let i = 0; i < questions.length; i++) {
const currentQuestion = questions[i]
// 检查当前题目的类型
if (currentQuestion.code === 'single_choice') {
// 如果当前题目是单选
// 检查上一个题目的类型是否与当前题目相同
if (i === 0 || questions[i - 1].code !== 'single_choice') {
// 如果上一个题目的类型与当前题目不同,创建新的分组数组
groupedQuestions.push([])
}
// 将当前题目添加到最后一个分组数组中
groupedQuestions[groupedQuestions.length - 1].push(currentQuestion)
} else if (currentQuestion.code === 'multiple_choice') {
// 如果当前题目是多选
// 检查上一个题目的类型是否与当前题目相同
if (i === 0 || questions[i - 1].code !== 'multiple_choice') {
// 如果上一个题目的类型与当前题目不同,创建新的分组数组
groupedQuestions.push([])
}
// 将当前题目添加到最后一个分组数组中
groupedQuestions[groupedQuestions.length - 1].push(currentQuestion)
} else if (currentQuestion.code === 'judgment') {
// 如果当前题目是判断
// 检查上一个题目的类型是否与当前题目相同
if (i === 0 || questions[i - 1].code !== 'judgment') {
// 如果上一个题目的类型与当前题目不同,创建新的分组数组
groupedQuestions.push([])
}
// 将当前题目添加到最后一个分组数组中
groupedQuestions[groupedQuestions.length - 1].push(currentQuestion)
}
}
this.listData = groupedQuestions
}
},
},
}
</script>
<style scoped lang="scss"></style>
样式代码:
.ac-sweep__choice { width:866px;
padding: 20px 0px;
}
.is-border {
border: 1px solid #000000;
border-bottom: none;
}
.is-border-bottom {
border-bottom: 1px solid #000000;
}
.ac-sweep__choice-box {
display: grid;
justify-items: flex-start;
grid-auto-flow: column;
// grid-template-columns: repeat(auto-fill, minmax(103px, 318px));
// grid-template-columns: repeat(auto-fill, minmax(min-content, auto));
// grid-template-rows: repeat(2, 20px);
padding: 9px 32px;
li {
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
margin-right: 28px;
&:last-child {
margin-right: 0px;
}
}
}
.ac-sweep__choice-item {
display: inline-flex;
padding-left: 11px;
.ac-sweep__choice-option {
position: relative;
width: 22px;
height: 12px;
line-height: 12px;
margin: 4px 8px 4px 0px;
text-align: center;
font-family: PingFangSC-Regular;
font-size: $--ac-font-size-small;
&:last-child {
margin-right: 0px;
}
}
.ac-sweep__choice-option::after,
.ac-sweep__choice-option::before {
position: absolute;
top: 0px;
width: 5px;
}
.ac-sweep__choice-option::before {
content: '[';
left: 0;
}
.ac-sweep__choice-option::after {
content: ']';
right: 0;
}
}
回答:
{ column: 5,direction: "横向",}// 横向纵向数据
handleList(list) {
return list.reduce((acc, cur, index, arr) => {
cur.index = index;
if (this.direction == "横向") {
(acc[index % this.column ? acc.length - 1 : acc.length] ||= []).push(cur);
} else if (this.direction == "纵向") {
(acc[index % Math.ceil(arr.length / this.column)] ||= []).push(cur);
}
return acc;
}, []);
https://codepen.io/15678871232/pen/JjeRXrg
以上是 如何实现这样一个布局? 的全部内容, 来源链接: utcz.com/p/934493.html