先上效果图:javascript
若是只是须要这样的表头,那么iview就能够作到(项目使用的iview),可是遇到这种既须要复杂表头,又须要跨行的状况,查了一下,好多都说让改iview源码,。。。就想着本身写一个。html
渣渣的我来讲,哈,颇有成就感。但愿你们提出建议。vue
下面是具体思路:java
1.首先是对表头的数据进行处理。npm
使用了和iview Table columns属性一样的格式存值。数组
columns : [ { title: '种类', key: 'type', //这一列值所对应的key hasrowspan:true // 在这里增长了一个属性,表示这一列是可能须要合并列的,后面会说 }, { title: '编制人数', key: 'amount', }, { title: '参数', children: [ //children表示参数下有子标题,能够嵌套多个children { title: '大小', key: 'size', align: 'center', }, ........ ], }, ......... ],
在处理columns时须要获得的数据有:app
2.处理表中的数据,数据的格式很简单,其中key值就是上面column中所对应的key,它将决定将值展现在哪一列。iview
dataList: [ { type: "图书", date: "2018-11-26", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "图书", date: "2018-11-26", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, ....... ],
在对这个数据进行处理时,要获得的数据有:ui
span:{} 格式以下,这是一个对象,表示哪一列的哪一行(对应td位置)rowspan的值(span中不存在时为1)
span:{ date: {0: 5, 5: 5}, //key为‘date’的列,第一个td须要跨5行,第六td须要跨5行 type: {0: 2, 2: 2, 4: 3, 7: 3} }
若是某一行有一列(td)跨了两行,那么它的下一行就要少一个tdthis
那么在这里就用少一个key来实现少一个td。
直接上完整代码:
<!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>多表头表格</title> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> </head> <body> <div id="app"> <table class="table"> <thead> <tr v-for="items in newArr"> <th v-for="item in items" :rowspan="item.rowspan" :colspan="item.colspan">{{item.title}}</th> </tr> </thead> <tbody v-if="needRowSpan.length>0"> <tr v-for="(items,index) in dataList"> <td v-for="item in items.tdList" :rowspan="resetRowSpan(index,item)">{{items[item]}}</td> </tr> </tbody> <tbody v-else> <tr v-for="(items,index) in dataList"> <td v-for="item in colKeyList">{{items[item]}}</td> </tr> </tbody> </table> </div> </body> <script> var app = new Vue({ el: '#app', data(){ return{ columns : [ { title: '种类', key: 'type', hasrowspan:true }, { title: '编制人数', key: 'amount', }, { title: '日期', key: 'date', hasrowspan:true }, { title: '参数', children: [ { title: '大小', key: 'size', align: 'center', }, { title: '参数1', key: 'param1', align: 'center', }, { title: '参数2', key: 'param2', align: 'center', }, { title: '参数3', key: 'param3', align: 'center', }, ], }, { title: '数据', align: 'center', children: [ { title: '数据1', key: 'infor1', align: 'center', }, { title: '数据2', key: 'infor2', align: 'center', }, { title: '数据3', key: 'infor3', align: 'center', }, { title: '数据4', key: 'infor4', align: 'center', }, ], }, ], //表头原始参数 newArr:[[]], //表头 maxHeight:1, //表头总共占的行数 colKeyList:[], //全部的key dataList: [ { type: "图书", date: "2018-11-26", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "图书", date: "2018-11-26", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "电子书", date: "2018-11-26", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "电子书", date: "2018-11-26", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "化妆品", date: "2018-11-26", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "化妆品", date: "2018-11-27", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "化妆品", date: "2018-11-27", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "水果", date: "2018-11-27", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "水果", date: "2018-11-27", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, { type: "水果", date: "2018-11-27", amount: 0, size: 0, param1: 0, param2: 0, param3: 0, infor1: 0, infor2: 0, infor3: 0, infor4: 0, }, ], //tbody具体数据 needRowSpan:[], //tbody须要跨行的key span:{} //所跨的行数 } }, mounted(){ this.maxHeight=this.getMaxFloor(this.columns); //1. 计算出表头一共须要多少行 this.columnsHandle(this.columns); //2. 对表头进行处理 this.dataHandle(this.dataList,this.needRowSpan); // 3. 对数据进行处理(传入参数: 具体数据,须要跨行列的(key)) }, methods: { resetRowSpan(row, key) { if (this.span[key] && this.span[key][row]) { return this.span[key][row]; } return 1; }, gerMaxCol(items) { let max = 0; function each(data) { if (max < data.length) { max = data.length; } data.forEach((item) => { if (item.children) { each(item.children); } }); } each(items); return max; }, getMaxFloor(treeData) { const that = this; let max = 0; function each(data, floor) { data.forEach((e) => { if (floor > max) { max = floor; } if (e.children && e.children.length > 0) { each(e.children, floor + 1); } }); } each(treeData, 1); return max; }, columnsHandle(treeData) { const that = this; const maxFloor = this.maxHeight; const keyList = []; function each(data, index) { if (that.newArr[index] === undefined) { that.newArr[index] = []; } data.forEach((e) => { const obj = { title: e.title, key: e.key, rowspan: maxFloor, colspan: 1, }; if (e.children) { obj.colspan = that.gerMaxCol(e.children); obj.rowspan = maxFloor - that.getMaxFloor(e.children); } else { that.colKeyList.push(e.key); if (e.hasrowspan) { // 若是存在hasrowspan属性而且值为true,则代表该key列存在跨行 that.needRowSpan.push(e.key); } } that.newArr[index].push(obj); if (e.children && e.children.length > 0) { each(e.children, index + 1); } }); } each(treeData, 0); }, dataHandle(dataList, needRowSpan) { needRowSpan.forEach((key) => { const sum = {}; let i = 0; let k = 0; const that = this; for (let j = 0; j < dataList.length; j += 1) { i += 1; let tdList = []; if (dataList[j].tdList) { tdList = [...dataList[j].tdList]; } else { tdList = [...that.colKeyList]; } if (dataList[j - 1] && (dataList[j][key] === dataList[j - 1][key] || !dataList[j][key])) { const index = tdList.indexOf(key); if (index > -1) { tdList.splice(index, 1); } } dataList[j].tdList = tdList; if (dataList[j + 1] && dataList[j + 1][key]) { if (dataList[j][key] !== dataList[j + 1][key]) { sum[k] = i; i = 0; k = j + 1; } } else if (!dataList[j + 1]) { sum[k] = i; } } this.span[key] = sum; }); console.log(this.span); this.showTable = true; }, } }); </script> <style> #app .table { width:100%; border-collapse:collapse; font-size:12px; color: #515a6e; border:1px solid #515a6e; } .table thead tr th{ height: 40px; white-space: nowrap; overflow: hidden; background-color: #f8f8f9; } td, th { text-align:center; border:1px solid #e8eaec; } /*tr:hover{*/ /*background:#EBF7FF;*/ /*}*/ .table thead tr th ,.table tbody tr td{ padding:0 10px; } .table tbody tr td{ height:48px; } </style> </html>