先上效果:
1.自定义表头:
通过设置 slot="header" 来自定义表头。 slot-scope="scope" 这一行千万不要因为没有再template中使用到scope,vscode报红而删除,这会导致input框不能输入任何内容!
<template slot="header" slot-scope="scope">//slot-scope="scope" 千万不要因为vscode报红删除<el-row :gutter="2"><el-col :span="12"><el-form-item:label="`病案号${caseIndex + 1}:`":prop="`data.${0}.patientList.${caseIndex}.bah`":rules="tableRuleForm.bah"><el-selectv-model="caseItem.bah"value-key="brid"placeholder="请输入关键词并回车"><el-optionv-for="item in medicalOptions":key="item.brid":label="item.bah":value="item"><span>{{ item.brxm }}:{{ item.bah }}</span></el-option></el-select></el-form-item></el-col><el-col :span="12"><el-form-itemlabel="病人姓名:":prop="`data.${0}.patientList.${caseIndex}.brxm`":rules="tableRuleForm.brxm"><el-input@change="$forceUpdate()"v-model="caseItem.brxm"size="mini"placeholder="请输入病人姓名"/></el-form-item></el-col></el-row>
</template>
2.多级表头和表头合并:
在 el-table-column 里面嵌套 el-table-column就可以实现多级表头。
<el-table-columnprop="amount1"v-for="(caseItem, caseIndex) in tableData.data[0].patientList":key="caseIndex"
><el-table-column prop="amount1" label="完全符合"><el-table-column prop="amount1" align="center" width="80"></el-table-column></el-table-column><el-table-column prop="amount1" label="部分符合"><el-table-column prop="amount1" align="center" width="80"></el-table-column></el-table-column>
</el-table-column>
因为下边还有要操作的单元格,所以总符合率这里必须要将三列合并为一列。所以我们要找到需要合并的单元格位置,使用 .colSpan 属性来合并单元格,这里循环是因为table的列是动态添加的所以进行循环合并,如果是固定的列,就不需要循环,直接找到要合并的列就行了。setColSpan方法一定要等table的dom全部渲染完成了才可以调用!否则获取不到节点。我这里是放在mounted()函数中并设置了一个setTimeout用了300毫秒的延时调用。
// 合并表头
setColSpan() {// 获取第三行的多级表头let row = document.getElementsByClassName("is-group")[0].getElementsByTagName("tr")[2];// console.log(row); //这里获取的表头排除了序号,检查项目,检查内容// 获取每一列let colAll = row.getElementsByTagName("th");// 循环列, .length -3 是减去序号,检查项目,检查内容这三列for (let index = 0; index < colAll.length - 3; index++) {if (index % 6 == 0) {// 只要当前列模以6是0就将本列加3(找到 不适用 下的这一列)的单元格的colSpan设为3row.getElementsByTagName("th")[index + 3].colSpan = 3;// 把接下来的两行设置为none 防止挤后边的row.getElementsByTagName("th")[index + 4].style.display = "none";row.getElementsByTagName("th")[index + 5].style.display = "none";}}
},
3.行内容一致的跨行合并:
通过给
table
传入span-method
方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row
、当前列column
、当前行号rowIndex
、当前列号columnIndex
四个属性。该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan
,第二个元素代表colspan
。 也可以返回一个键名为rowspan
和colspan
的对象。
<el-table:data="tableData.data":span-method="objectSpanMethod"borderheight="calc(100vh - 280px)"style="width: 100%"class="table">
</el-table>
下边是方法
// 合并行
objectSpanMethod({ row, column, rowIndex, columnIndex }) {const dataProvider = this.tableData.data;if (columnIndex === 1) {const prevRow = dataProvider[rowIndex - 1]; //上一条数据let nextRow = dataProvider[rowIndex + 1]; //下一条数据// 如果上一条数据存在并且上一条数据和当前数据相同,那么就不渲染这个单元格if (prevRow && prevRow.BZMC === row.BZMC) {return { rowspan: 0, colspan: 0 };//不相同判断如何渲染} else {let rowspan = 1;// 如果下一条数据和当前数据相同那么应该合并单元格 while判断下边有几行和当前数据相同,while直到找到不相同的退出循环while (nextRow && nextRow.BZMC === row.BZMC) {rowspan++;// 只要当前行和下一行相同,那么对比rowspan加下一条数据是否相同nextRow = dataProvider[rowspan + rowIndex];}if (rowspan > 1) {return { rowspan, colspan: 1 };}}}
},
这里用while循环来判断到底进行多少次跨行合并。
4.table动态新增列的时候表格中间出现一大片空白,样式错乱
因为我这个table的列是动态新增的,在病案历数select框中我多选择一例就会新增病案号,病人姓名这几列。所以病案号是一个数组循环出来的列,我新增的时候push进去一个病人信息对象,table重新被渲染。渲染的时候table会闪一下然后出现一大片空白,如图:
具体原因不知道为什么,但是我猜测是因为我直接对渲染的table :data="tableData" 进行了操作导致的,所以我的解决方法是先拷贝一份当前渲染的tableData,操作拷贝的这个对象,最后先将tableData赋空,再把拷贝的对象赋值给tableData,这样就完美解决了。
changeCaseNum(value) {//深拷贝一份当前正在渲染的tableData进行操作let data = JSON.parse(JSON.stringify(this.tableData.data));if (data[0].patientList.length < value) {while (data[0].patientList.length < value) {data.forEach((item) => {item.patientList.push({fz: "100.00",bah: "",brxm: "",df: "0",wqfhs: data.length,bffhs: 0,bfhs: 0,});});}} else {data.forEach((item) => {item.patientList.splice(value);});}//先将当前渲染的talbeData 赋空this.tableData.data = [];//然后再将拷贝的data赋值给el-talbe渲染setTimeout(() => {this.tableData.data = data;});// 重新调用合并表头的方法setTimeout(() => {this.setColSpan();}, 300);
},
记得操作完table之后要重新调用 setColSpan()进行表头合并。