今天,在vue
中遇到 复杂表格的渲染 ,须要合并表头th
的单元格,且合并单元格的那列的表头数据是动态数据,也就是不知道会有多少个表头列,而这几个表头列还分了好几个子表头
。vue
这个需求在js里用Juicer模板很好作的,思路我是有的,但就是对于vue
,我也算初学者,不少概念不是很懂,这就限制了思路。ios
在网上搜了不少合并单元格的都是简单的数据合并,也就是td
合并, 不是咱们的需求,就不贴了。git
哎,废话很少说了,看代码吧:github
iviewui
的table
组件:最初,直接使用项目中的iviewui
的table
组件, 给 column 设置 children ,能够实现表头合并。先用写死的数据作了个样例,以下:数据库
<Table :columns="columns" :data="studentData" border></Table>
data()中以下:json
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' } ],
实现效果如图:axios
如下是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是根据数据循环生成的,请仔细看这里给出的数据格式。iview
template以下:ui
<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
组件 能作出来动态列数的表头合并,欢迎来一块儿谈论办法!!!