吐槽
今天,在vue
中遇到 復雜表格的渲染 ,需要合並表頭th
的單元格,且合並單元格的那列的表頭數據是動態數據,也就是不知道會有多少個表頭列,而這幾個表頭列還分了好幾個子表頭
。
這個需求在js里用Juicer模板很好做的,思路我是有的,但就是對於vue
,我也算初學者,很多概念不是很懂,這就限制了思路。
在網上搜了很多合並單元格的都是簡單的數據合並,也就是td
合並, 不是我們的需求,就不貼了。
哎,廢話不多說了,看代碼吧:
代碼示例
使用iviewui
的table
組件:
最初,直接使用項目中的iviewui
的table
組件, 給 column 設置 children ,可以實現表頭合並。先用寫死的數據做了個樣例,如下:
<Table :columns="columns" :data="studentData" border></Table>
data()中如下:
columns: [
{
title: '序號',
width: 60,
align: 'center',
fixed: 'left',
render: (h, params) => {
return h('span', params.row._index + 1)
}
},
{
title: '姓名',
key: 'name',
align: 'center',
fixed: 'left',
width: 80
},
{
title: '學號',
key: 'code',
align: 'center',
width: 80
},
{
title: '性別',
key: 'sex',
align: 'center',
width: 80
},
{
title: '學期',
key: 'term',
align: 'center',
width: 80
},
{
title: '9月28日',
align: 'center',
children: [
{
title: '閱讀',
key: 'date1_rScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '聽力',
key: 'date1_lScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '寫作',
key: 'date1_wScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '口語',
key: 'date1_sScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '總分',
key: 'date1_score',
align: 'center',
minWidth: 80,
sortable: true
}
]
},
{
title: '8月10日&14日',
align: 'center',
children: [
{
title: '閱讀',
key: 'date2_rScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '聽力',
key: 'date2_lScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '寫作',
key: 'date2_wScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '口語',
key: 'date2_sScore',
align: 'center',
minWidth: 80,
sortable: true
},
{
title: '總分',
key: 'date2_score',
align: 'center',
minWidth: 80,
sortable: true
}
]
},
{
title: '聽力提高',
key: 'lImprove',
align: 'center',
width: 70
},
{
title: '閱讀提高',
key: 'rImprove',
align: 'center',
width: 70
},
{
title: '寫作提高',
key: 'writingImprove',
align: 'center',
width: 70
},
{
title: '口語提高',
key: 'sImprovem',
align: 'center',
width: 70
},
{
title: '總分提高',
key: 'srImprove',
align: 'center',
width: 70
}
],
studentData: [
{
name: 'xxx',
code: '918989070065',
sex: '男',
term: '2018秋',
date1: '9月28日',
date1_rScore: '3.5',
date1_lScore: '3.5',
date1_wScore: '5',
date1_sScore: '4',
date1_score: '4',
date2: '8月10日&14日',
date2_rScore: '3.5',
date2_lScore: '3.5',
date2_wScore: '5',
date2_sScore: '4',
date2_score: '4',
lImprove: '-0.5',
rImprove: '0',
wImprove: '1.5',
sImprove: '0.5',
srImprove: '0.5'
}
],
實現效果如圖:
重點是后端給的數據格式
以下是data
數據是后端接口返回的,其中的數據格式是這樣的:
[
{
"studentId": "ff808b937f50a33",
"studentName": "傅xx",
"studentCode": "91scdsc109",
"sex": {
"value": "MALE",
"name": "男"
},
"termName": "2018秋",
"examDates": [
"10月",
"9月28日"
],
"map": {
"9月28日": [
{
"courseName": "聽力",
"score": 6.0
},
{
"courseName": "閱讀",
"score": 7.0
},
{
"courseName": "寫作",
"score": 5.5
}
]
},
"courseNames": [
"聽力",
"閱讀",
"寫作",
"口語",
"總分"
]
},
{
"studentId": "ff80c52801bc",
"studentName": "陳xx",
"studentCode": "91edfedf3",
"sex": {
"value": "FEMALE",
"name": "女"
},
"termName": "2018秋",
"examDates": [
"10月",
"9月28日"
],
"map": {
"9月28日": [
{
"courseName": "聽力",
"score": 5.5
},
{
"courseName": "閱讀",
"score": 6.0
},
{
"courseName": "寫作",
"score": 5.5
},
{
"courseName": "口語",
"score": 5.5
}
]
},
"courseNames": [
"聽力",
"閱讀",
"寫作",
"口語",
"總分"
]
}
]
重點是要以上述data
中map
里的日期
為一組的表頭,每組日期包含的是五門課,然后日期是根據數據庫查出來的,不確定到底是幾個日期
,也就是table里這個日期的th是根據數據循環生成的,請仔細看這里給出的數據格式。
使用H5的table實現
template如下:
<table class="table">
<thead>
<tr>
<th rowspan="2">序號</th>
<th rowspan="2">姓名</th>
<th rowspan="2">學號</th>
<th rowspan="2">性別</th>
<th rowspan="2">學期</th>
<th colspan="5" v-for="(it,i) in examDates" :key="i">{{it}}</th>
</tr>
<tr>
<template v-for="itd in examDates">
<th v-for="(itc,j) in courseNames" :key="itd+j">{{itc}}</th>
</template>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in studentDataList" :key="index">
<td>{{index+1}}</td>
<td>{{item.studentName}}</td>
<td>{{item.studentCode}}</td>
<td>{{item.sex.name}}</td>
<td>{{item.termName}}</td>
<template v-for="examDate in examDates">
<template v-for="(course,j) in courseNames">
<td :key="examDate+j">
{{initScoreFinal(examDate,course,item.map)}}
</td>
</template>
</template>
</tr>
</tbody>
</table>
獲取到上述后端返回的數據后,對數據稍微處理下:
data () {
return {
studentDataList: [],
examDates: [],
courseNames: []
},
created () {
this.getData ()
},
methods: {
//
getData () {
this.$get( //該方法是封裝過的axios
'/list.json',
{
....//此處是參數,略
},
response => {
this.examDates = response.data[0].examDates
this.courseNames = response.data[0].courseNames
this.studentDataList = response.data
}
)
},
initScoreFinal (examDate, course, map) {
let final = 0
console.log('map:' + map)
for (var it in map) {
map[it].forEach((item, index, array) => {
if (it === examDate && item.courseName === course) {
final = item.score
}
})
}
return final
}
}
效果如圖:
再吐個槽
在網上搜了很多合並單元格的都是簡單的數據合並,也就是td
合並,
我們這邊的項目需要的這個表格比較變態,結合上述效果圖來說吧,圖中的表頭是先按日期為一列th
,這日期的列下分五門課程的子列th
,且日期數目不定,可能是一兩個日期,可能是多個日期,每個日期下對應的課程也不確定,就像學生上課,每天的課不同,但總共就那五門課,日期列的數目不定,課程數的數據不定,於是,這就很頭疼了-_-||
總之長知識了,記錄下來。
或許有大神能用iviewui
的table
組件 能做出來動態列數的表頭合並,歡迎來一起談論辦法!!!