如何实现这样一个布局?

如何实现这样一个布局?
要求是这样的(目前的话换行单选多选判断换行展示已经处理完了):
如何实现这样一个布局?
但是现在有个问题就是选项的个数问题,选项最多是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

回到顶部