动态获取数据渲染到页面上,不使用el-table,使用的布局是el-row和el-col,实现布局,如何将相同行,以及依赖相同行的相同行合并,有点绕,看代码吧,有兴趣的朋友也可以一起探讨呀。比心
现在页面是这样的:
想实现将红框中数据合并:
我已经对后台数据做了一些处理,将数据根据secondContent(二级检验内容)分为:
有children 的和 没有children 的。
先看后台返回的数据结构:
这是主要代码
<div class="container">
<div class="right">
<el-row class="b3">
<el-col :span="3" class="info info2 bdt"><span>检验内容</span></el-col>
<el-col :span="14" class="info info2 bdt"><span>检验项目</span></el-col>
<el-col :span="2" class="info info2 bdt"><span>检查结果</span></el-col>
<el-col :span="5" class="info info2 bdt"><span>备注</span></el-col>
</el-row>
<!-- 具体数据 -->
<!-- 有孩子的-->
<el-row class="b3" v-for="(item,index) in form.arrHasChildren" :key="index">
<!-- 检验内容-->
<el-col :span="3" class="info info2"
style="height:50px;display: flex">
<el-row class="b3 bdr" style="width: 50%;line-height: initial;">
<span>{{item.mainContent}}</span>
</el-row>
<el-row class="b3 bdr" style="width: 50%;line-height: initial;">
<span>{{item.secondContent}}</span>
</el-row>
</el-col>
<!-- 检验项目-->
<el-col :span="14" class="info info2">
<span>{{item.testProject}}</span>
</el-col>
<!-- 结果-->
<el-col :span="2" class="info info2">
<span>{{item.result}}</span>
</el-col>
<!-- 备注-->
<el-col :span="5" class="info info2">
<span>{{item.note}}</span>
</el-col>
</el-row>
<!-- 没有孩子-->
<el-row class="b3" v-for="(item,index) in form.arrNoChildren" :key="index">
<!-- 检验内容-->
<el-col :span="3" class="info info2">
<el-row class="b3">
<el-col><span>{{item.mainContent}}</span></el-col>
</el-row>
</el-col>
<!-- 检验项目-->
<el-col :span="14" class="info info2">
<span>{{item.testProject}}</span>
</el-col>
<!-- 结果-->
<el-col :span="2" class="info info2">
<span>{{item.result}}</span>
</el-col>
<!-- 备注-->
<el-col :span="5" class="info info2">
<span>{{item.note}}</span>
</el-col>
</el-row>
</div>
</div>
后台数据是模拟的,所以朋友们不必关注请求问题
script代码:
<script src="./js/vue.js"></script>
<script src="./js/elementui.js"></script>
<script src="./js/vue-resource.min.js"></script>
<script>
new Vue({
el: '#app',
data: function () {
return {
form: {
testDate: [], //每条记录
arrHasChildren: [], //有孩子的
arrNoChildren: [], //没有孩子的
},
inputValue: '',
}
},
created() {
this.postMessage()
// window.callJsFunction = this.callJsFunction
},
methods: {
getMessage() {
this.$http.get('http://localhost:3003/report').then(function (result) {
console.log(result.body)
// console.log(this.form.arrHasChildren.length)
})
},
postMessage() {
this.$http.post('http://localhost:3003/report', {}).then(function (result) {
this.inputValue = result.body.ReportTitle
const data = result.body.data
this.form.testDate = data
let arrHasChildren = []
let arrNoChildren = []
for (let i = 0; i < this.form.testDate.length; i++) {
// let objHasChildren ={}
//有二级检验内容secondcontent的提取出来
if (this.form.testDate[i].secondContent !== '') {
arrHasChildren.push(this.form.testDate[i])
} else {
//没有的
arrNoChildren.push(this.form.testDate[i])
}
}
this.form.arrHasChildren = arrHasChildren
this.form.arrNoChildren = arrNoChildren
})
}
}
});
</script>
问题就是这样啦,我现在有一个想法,不知道行不行得通,讨论一下:
就是再改变一下数据结构,
分别对已经分了类的两组数据进行循环,
对于有children的数组:
1.设置一个新数组
2.每组数据从第二条数据开始,与上一条数据进行比较,判断mianContent的内容是否一样。
一样的话设置新对象将mianContent放进去,再放进新数组中。执行步骤3
不一样的话。执行步骤4
3.然后继续比较secondContent的内容是否一样。
一样的话设置新对象将secondContent放进去,并将这两条数据也放进去。执行步骤4
此时数结构希望是这样的:
javascript
[ {
"mainContent": "AA",
{
"secondContent": "b",
{
"mainContent": "AA",
"secondContent": "b",
"testProject": "日常运行",
"result": "",
"note": ""
},
{
"mainContent": "AA",
"secondContent": "b",
"testProject": "哈哈哈哈哈哈哈哈哈哈",
"result": "",
"note": ""
}
}
}
]
不一样的话也是设置一个新数组,但是此时是将这两条数据都放进去,不将secondContent单独提取出来。 执行步骤4
此时数结构希望是这样的:
[ {
"mainContent": "AA",
{
"mainContent": "AA",
"secondContent": "b",
"testProject": "日常运行哈d哈哈",
"result": "",
"note": ""
},
{
"mainContent": "AA",
"secondContent": "c",
"testProject": "日常运行哈d哈哈",
"result": "",
"note": ""
}
}
]
4.本次循环结束,当前这条数据将作为被比较对象,与下一条数据继续比较,也就是执行步骤2
5.最后根据输出的:已经提取出来了相同的部分,然后进行布局
目前就是这样了,我不知道这个想法行得通不,只是想,还不敢做,如果您有什么想法,可以在评论区下评论,或者私信我也可以哦!欢迎一起讨论,一起进步!
返回的数据中多加2个字段,col和row,这样就可以根据col和row来判断了,如果接口返回的数据没法给你这俩个字段,那么可以在渲染的时候先把数据处理一下,加上row,col字段,这样就成为了怎么组织数据的问题了。
这不就是你要的结果嘛
上代码:没有优化,可以自己再优化一下数据。
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
.table{
width: 100%;
border: 1px solid #ccc;
}
.table td{
text-align: center;
border: 1px solid #ccc;
height: 40px;
}
</style>
<body>
<div id="container">
<table class="table">
<template v-for="l in list">
<tr>
<template v-for="ll in l">
<td :colspan="ll.col" :rowspan="ll.row">{{ll.content}}</td>
</template>
</tr>
</template>
</table>
</div>
</body>
<script src="./vue-2.6.14.min.js"></script>
<script>
let vue = new Vue({
el: "#container",
data: {
list: [
[
{ content: '项目名称', col: 2, row: 1 },
{ content: '热介质锅炉检测报告', col: 3, row: 1 }
],
[
{ content: '检验内容', col: 2, row: 1 },
{ content: '检验项目', col: 1, row: 1 },
{ content: '检查结果', col: 1, row: 1 },
{ content: '备注', col: 1, row: 1 }
],
[
{ content: '安全附件和仪表', col: 1, row: 4 },
{ content: '安全阀', col: 1, row: 4 },
{ content: '安全阀是否在检验有效', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
{ content: '', col: 1, row: 1 }
],
[
{ content: '安全阀是否泄露', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
{ content: '', col: 1, row: 1 }
],
[
{ content: '压力表外观读书是否一致', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
{ content: '', col: 1, row: 1 }
],
[
{ content: '压力表是否损坏', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
{ content: '', col: 1, row: 1 }
],
[
{ content: 'ijsss', col: 1, row: 1 },
{ content: 'o2jfjnf', col: 1, row: 1 },
{ content: '日常运行哈d哈哈', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
],
[
{ content: '安全管理情况', col: 2, row: 2 },
{ content: '日常运行记录是否正常', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
{ content: '', col: 1, row: 1 }
],
[
{ content: '日常运行哈哈哈', col: 1, row: 1 },
{ content: '', col: 1, row: 1 },
{ content: '', col: 1, row: 1 }
],
]
},
methods: {
}
});
</script>
</html>
就是显示几个label嘛,返回一个数组遍历不就可以了
<template>
<div>
<el-row v-for="(item, index) in list" :key="index">
<el-col :span="3">
<el-row class="label">
<el-col v-for="(cItem, cIndex) in item.contents" :key="cIndex">
<span class="cell">{{ cItem }}</span>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data () {
return {
list: [
{ contents: ['安全仪表'] },
{ contents: ['安全仪表', '安全阀'] },
{ contents: ['安全仪表', '压力表'] },
{ contents: ['压力表'] }
]
}
}
}
</script>
<style lang="scss" scoped>
.label {
display: flex;
text-align: center;
}
.cell {
display: block;
border: 1px solid #ccc;
margin: -1px 0 0 -1px;
}
</style>
使用el-table表示是最简单的,element-u中的表格提供了合并单元格的属性。
推荐一波vxe-table组件,里面有现成的组件,
https://vxetable.cn/v3/#/table/advanced/span
在乎排序吗?不在乎的话可以考虑用map,不要在意样式。
let newMap = new Map();
this.list.forEach(item => {
let key = item.secondContent ? `${item.mainContent}-${item.secondContent}` : `${item.mainContent}`;
let current = newMap.get(key);
if (current) {
current.push(item)
newMap.set(key, current);
} else {
newMap.set(key, [item])
}
});
this.map = newMap;
<div class="right">
<el-row class="b3">
<el-col :span="3" class="info info2 bdt"
><span>检验内容</span></el-col
>
<el-col :span="14" class="info info2 bdt"
><span>检验项目</span></el-col
>
<el-col :span="2" class="info info2 bdt"
><span>检查结果</span></el-col
>
<el-col :span="5" class="info info2 bdt"
><span>备注</span></el-col
>
</el-row>
<el-row v-for="key in map.keys()" :key="key">
<el-row>
<el-col
:span="3"
class="info info2"
style="display: flex"
>
<el-col :span="key.includes('-') ? 12 : 24">{{ key.split("-")[0] }}</el-col>
<el-col v-if="key.includes('-')" :span="12">
{{ key.split("-")[1] }}
</el-col>
</el-col>
<el-col :span="21">
<el-col
v-for="item in map.get(key)"
:key="item.id"
>
<!-- 检验项目-->
<el-col :span="14" class="info info2">
<span>{{ item.testProject }}</span>
</el-col>
<!-- 结果-->
<el-col :span="2" class="info info2">
<span>{{ item.result }}</span>
</el-col>
<!-- 备注-->
<el-col :span="5" class="info info2">
<span>{{ item.note }}</span>
</el-col>
</el-col>
</el-col>
</el-row>
</el-row>
</div>
element ui table不是有合并行或列吗
要是复杂了那就自己改造一下白
vue 相同列合并
现成的可以直接用
<template>
<div class="content_home">
<div class="content_home_start">
<div class="conter_table">
<el-row :gutter="11">
<el-col :span="3">
<el-select placeholder="地点"
type="text"
v-model="earecode"
autocomplete="off"
>
<el-option
v-for="item in eareOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-col>
<!-- <el-col :span="3">
<el-select v-model="findcolumn" placeholder="查询项">
<el-option
v-for="item in columnOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-col>
<el-col :span="3">
<el-input v-model="findcontent" placeholder="查询内容">
</el-input>
</el-col> -->
<el-col :span="2">
<el-button type="primary" style="width: 100%" @click="findRegPersonList">
<i class="el-icon-search"></i>查询</el-button
>
</el-col>
</el-row>
<!--下方为日程列表-->
<el-table
:data="tableDataList"
:span-method="spanMethod"
border
style="width: 70%; margin-top: 20px; margin-left;: 1000px">
<el-table-column
prop="eareid"
type="selection"
width="55">
</el-table-column>
<el-table-column
prop="eareid"
label="序号"
type="index"
width="50">
</el-table-column>
<el-table-column
prop="earename"
label="地市"
width="180">
</el-table-column>
<el-table-column
prop="examdays"
label="考试天数"
width="180">
</el-table-column>
<el-table-column
prop="examdate"
label="考试日期">
</el-table-column>
<el-table-column label="操作" align="center" width="320">
<template slot-scope="scope">
<el-button type="primary" plain size="mini" @click="showdetail(scope.row)">详细</el-button>
<el-button type="primary" plain size="mini" v-if="scope.row.empowerType=='1' ||scope.row.empowerType=='0' " @click="closeEmpowerType(scope.row)">关闭授权</el-button>
<el-button type="primary" plain size="mini" v-if="scope.row.empowerType=='2'" @click="openEmpowerType(scope.row)">开启授权</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
style="margin-top: 15px;"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="pageSizes"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
</div>
</template>
<script>
import { } from '@/api/person';
export default {
name: 'pershenhe',
components: {
},
data() {
return {
currentPage: 1,
pageSizes: [2,5,10, 30, 50, 100, 200, 300],
pageSize: 10,
total: 0,
perlist:[] ,
columnOptions:[],//查询项
eareOptions:[],//查询考点
findcolumn:"",
earecode:"" ,
findcontent: "" ,
tableDataList: [{
eareid:'17',
earename: '信阳',
examdays: '4',
examdate: '2023-07-01',
empowerType:'0'
}, {
eareid:'17',
earename: '信阳',
examdays: '4',
examdate: '2023-07-02',
empowerType:'1'
}, {
eareid:'17',
earename: '信阳',
examdays: '4',
examdate: '2023-07-07',
empowerType:'2'
}, {
eareid:'17',
earename: '信阳',
examdays: '4',
examdate: '2023-07-08',
empowerType:'0'
}, {
eareid:'14',
earename: '商丘',
examdays: '3',
examdate: '2023-07-01',
empowerType:'0'
}, {
eareid:'14',
earename: '商丘',
examdays: '3',
examdate: '2023-07-02',
empowerType:'1'
}, {
eareid:'14',
earename: '商丘',
examdays: '3',
examdate: '2023-07-07',
empowerType:'2'
}
, {
eareid:'15',
earename: '周口',
examdays: '1',
examdate: '2023-07-01',
empowerType:'1'
}],
spanMap: {},
};
},
mounted() {
this.getRegPersonList();
this.getInitOptionsData();
this.initSpanArr(this.tableDataList, 'earename');
this.initSpanArr(this.tableDataList, 'examdays');
},
methods: {
// 合并单元格
spanMethod( {rowIndex, column: {property}} ){
if(this.spanMap[property]){
const _row = this.spanMap[property].spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return { // [0,0] 表示这一行不显示, [2,1]表示行的合并数
rowspan: _row,
colspan: _col,
};
}
},
// 单元格合并方法
initSpanArr( data, column ){
let contactDot = 0;
this.spanMap[column] = {};
this.spanMap[column].spanArr = [];
data.forEach(( item, index ) => {
if(index === 0){
this.spanMap[column].spanArr.push(1); // 第一行数据 不合并
} else {
if(item[column] === data[index - 1][column]){
this.spanMap[column].spanArr[contactDot] += 1; // 下一行,如果数据相同,合并行数加一
this.spanMap[column].spanArr.push(0);
} else{
contactDot = index;
this.spanMap[column].spanArr.push(1);
}
}
});
},
// 关闭授权
closeEmpowerType(row) {
},
// 开启授权
openEmpowerType(row) {
},
// 展示授权详情
showdetail(row) {
console.log(row);
},
getSpanArr(data) {
this.spanArrOrd = []
},
headClass() {
// 表格table头第一行的背景
return "text-align: center;background:#eef1f6;";
},
getInitOptionsData(){
this.getEareSel();
this.getColumnOp();
},
findRegPersonList(){
this.currentPage = 1
this.getRegPersonList()
},
getRegPersonList(){
},
handleSizeChange(val) {
//改变每页条数的动作事件
this.pageSize = val;
this.currentPage = 1; //改变每页条数,从第一页开始
this.getRegPersonList();
},
handleCurrentChange(val) {
//改变页数的动作事件
this.currentPage = val;
this.getRegPersonList();
},
getEareSel(){
//获取考点下拉选
this.eareOptions=[{value:"",label:"请选择考点地区"},{value:"1",label:"省直"},{value:"2",label:"郑州市"},{value:"3",label:"开封市"},{value:"4",label:"洛阳市"},{value:"5",label:"平顶山市"},{value:"6",label:"新乡市"},
{value:"7",label:"焦作市"},{value:"8",label:"濮阳市"},{value:"9",label:"鹤壁市"},{value:"10",label:"安阳市"},{value:"11",label:"三门峡市"},{value:"12",label:"许昌市"},
{value:"13",label:"漯河市"},{value:"14",label:"商丘市"},{value:"15",label:"周口市"},{value:"16",label:"驻马店市"},{value:"17",label:"信阳市"},{value:"18",label:"南阳市"},
{value:"19",label:"济源市"},{value:"28",label:"新蔡县"},{value:"35",label:"巩义市"},{value:"37",label:"永城市"},{value:"38",label:"固始"},{value:"39",label:"邓州市"},
{value:"41",label:"兰考县"},{value:"42",label:"汝州市"},{value:"43",label:"滑县"},{value:"44",label:"长垣县"},{value:"45",label:"鹿邑县"},]
},
getColumnOp(){
this.columnOptions=[{value:"",label:"请选择查询项"},{value:"username",label:"账户"},{value:"responsname",label:"负责人姓名"},{value:"respstelpone",label:"负责人联系方式"},
{value:"operator",label:"操作人姓名"},{value:"operatortel",label:"操作人联系方式"}]
},
},
};
</script>
<style .scoped>
.content_home_start {
padding: 10px;
box-sizing: border-box;
width: 100%;
height: 100%;
}
.conter_table {
margin-top: 10px;
/* height: 600px; */
/* padding: 35px 15px;
border-radius: 5px;
border: 1px solid gray;
box-sizing: border-box; */
}
.el-dialog__body {
padding: 2px 20px;
color: #606266;
font-size: 14px;
word-break: break-all;
}
.el-row ::v-deep .el-input__inner{
height: 40px;
}
.el-input--medium .el-input__inner {
height: 40px;
line-height: 40px;
}
</style>
你后台的数据咋返回这种
在Element UI中,使用el-row和el-col可以很方便的实现栅格布局,其中el-row定义行,el-col定义列。在一些情况下,可能需要合并相邻行或列中的内容,以达到更好的布局效果。本文将介绍如何合并相同的el-row和el-col内容。
在el-row中,可以使用justify属性来定义行内元素的对齐方式。其中的space-between属性可以让元素等间距分布在行中。如果希望将相邻的行合并起来,可以在el-row中使用同样的class名,然后在CSS中定义样式,让相邻的行间距为0。这样,就可以达到合并相同el-row内容的效果。
例如:
<template>
<div>
<el-row class="row">Row 1</el-row>
<el-row class="row">Row 2</el-row>
<el-row class="row">Row 3</el-row>
<el-row class="row">Row 4</el-row>
</div>
</template>
<style>
.row {
margin-bottom: 10px;
}
.row + .row {
margin-top: 0;
}
</style>
在上面的代码中,我们为所有的el-row添加了class名“row”,然后使用CSS将相邻的行间距调整为0。这样,就可以实现合并相邻el-row的效果。
在el-col中,可以使用span属性来定义元素跨越的列数。如果希望将相邻的列合并起来,可以在el-col中使用同样的class名,然后在CSS中定义样式,将所有相邻的列的宽度设置为100%。这样,就可以达到合并相同el-col内容的效果。
例如:
<template>
<el-row>
<el-col class="col" :span="12">Column 1</el-col>
<el-col class="col" :span="12">Column 2</el-col>
<el-col class="col" :span="6">Column 3</el-col>
<el-col class="col" :span="6">Column 4</el-col>
<el-col class="col" :span="6">Column 5</el-col>
<el-col class="col" :span="6">Column 6</el-col>
</el-row>
</template>
<style>
.col {
float: left;
margin-bottom: 10px;
}
.col + .col {
clear: left;
width: 100%;
}
</style>
在上面的代码中,我们为所有的el-col添加了class名“col”,然后使用CSS将相邻的列的宽度设置为100%。这样,就可以实现合并相邻el-col的效果。另外,我们还使用了float属性将列向左浮动,并使用clear属性清除浮动。这样,可以让所有列在同一行显示。
综上所述,合并相同的el-row和el-col内容可以极大地优化布局效果。需要注意的是,合并行或列时需要使用同样的class名,并在CSS中定义相应的样式。同时,也需要考虑到元素的浮动和清除浮动等问题,以达到最优的布局效果。
在Element UI中,el-row和el-col是常用的布局组件,用于进行页面布局和排版。el-row代表一行,el-col则代表一列,可以通过它们的属性来控制宽度、间距等布局信息。在实际开发中,我们可能会遇到需要将相同列内容进行合并的情况。本文将详细介绍如何使用Element UI实现el-row和el-col内容的合并。
一、使用v-for循环渲染
我们可以使用v-for指令循环渲染el-col组件,在渲染时通过添加相应的属性来实现行列合并的效果。具体方法如下:
<el-row>
<el-col v-for="(item, index) in dataSource" :key="index" :span="item.colspan" :offset="item.offset" :xs="item.xs" :sm="item.sm" :md="item.md" :lg="item.lg" :xl="item.xl">
{{ item.text }}
</el-col>
</el-row>
data() {
return {
dataSource: [
{
text: '第一列内容',
colspan: 4,
offset: 2,
xs: { span: 12 },
sm: { span: 8, offset: 2 },
md: { span: 6, offset: 3 },
lg: { span: 4 },
xl: { span: 3 }
},
{
text: '第二列内容',
colspan: 2,
xs: { span: 12 },
sm: { span: 8, offset: 2 },
md: { span: 6, offset: 3 },
lg: { span: 4 },
xl: { span: 3 }
},
{
text: '第三列内容',
colspan: 2,
xs: { span: 12 },
sm: { span: 8, offset: 2 },
md: { span: 6, offset: 3 },
lg: { span: 4 },
xl: { span: 3 }
}
]
}
}
在上面的代码中,我们定义了三个元素对象,每个对象的属性包括:text-列中的文本内容, colspan-跨越的列数,offset-列偏移量, xs/sm/md/lg/xl-响应式布局下的列宽和偏移量。
通过使用v-for指令循环渲染el-col组件,对于第一个元素对象,设置colspan为4,所以该列会跨越4列;offset为2,列偏移量为2;xs占12列,分别为8列和4列;sm占8列并向右偏移2列,md占6列并向右偏移3列,lg占4列, xl占3列。最终呈现效果如下所示:
二、使用嵌套布局方式
另一种方法是使用嵌套布局方式,通过将el-row和el-col组件进行嵌套,实现内容的合并。具体方法如下:
<el-row>
<el-col :span="16">
<el-row>
<el-col :span="12">第一列内容</el-col>
<el-col :span="6">第二列内容</el-col>
<el-col :span="6">第三列内容</el-col>
</el-row>
</el-col>
<el-col :span="8">第四列内容</el-col>
</el-row>
在上面的代码中,我们将第一列、第二列和第三列的内容放入一个新的el-row组件中,将它们作为子元素嵌套到父元素的el-col中,实现合并的效果。同时,我们也可以在el-col组件上添加其他属性,如offset、xs、sm、md、lg和xl等,以控制子元素的布局信息。
最终呈现效果如下所示:
总结
本文主要介绍了如何使用Element UI实现el-row和el-col内容的合并。我们可以使用v-for循环渲染或者使用嵌套布局的方式来实现合并效果。在实际开发中,根据需求和场景的不同,我们需要选择最合适的方法来进行行列合并,以达到最佳的布局效果。