Vxetable v3.6.9
合并单元格+虚拟滚动问题
使用版本
vue:2.7.16
vxe-table:3.6.9
下面示例使用的是
:scroll-y="{}"
加:merge-cells="{}"
方式
重要说明 本案例使用的的版本比较老,因为是老项目。官网连接:Vxe Table v3.8
示例:这里使用 虚拟滚动+ 合并单元格单元格方式
需求说明:实现根据层级实现一对多合并单元格,并且数据量大
说明:这里代码示例是使用的项目中封装方法。
封装组件ElXTable/index.vue
vue
<template>
<vxe-table
id="eTable"
ref="singleTable"
class="my-vxe-table"
:scroll-y="{ enabled: isVirtual, gt: 0, mode: 'wheel', ...scrollY }"
:height="height"
:data="pageData.data || dataList"
border
show-overflow
keep-source
:row-id="rowKey"
size="medium"
:merge-cells="mergeCells"
>
<slot />
</vxe-table>
// 分页
<vxe-pager
:hide-on-single-page="false"
:current-page="pageData.currentPage"
:page-sizes="[50, 100, 200, 500, 1000]"
:page-size="pageData.pageSize"
size="small"
:pager-count="5"
:layouts="['Total', 'Sizes', 'PrevPage', 'JumpNumber', 'NextPage', 'FullJump']"
:total="pageData.total"
@page-change="handleCurrentChange"
/>
</div>
</template>
<script>
export default {
methods:{
// 获取当前表格的列 {collectColumn, fullColumn, visibleColumn, tableColumn}
getTableColumn() {
return this.$refs.singleTable.getTableColumn().fullColumn
},
// 获取表格的可视的列 Array (及不包含隐藏的列 - 工具栏隐藏功能)
getColumns() {
return this.$refs.singleTable.getColumns()
}
}
}
</script>
page/index.vue
vue
<template>
<ElXTable
ref="xTable"
isVirtual
rowKey="id"
:dataList="tableData"
:mergeCells="mergeCells"
>
<vxe-column type="checkbox" width="60" />
<vxe-column type="seq" title="序号" width="55" />
<vxe-column field="data1" title="数据1"></vxe-column>
...
</ElXTable>
</template>
<script>
import ElXTable from "@/components/ElXTable"
export default {
components: {
ElXTable
},
data() {
return {
tableData: [], // 表格数据
mergeCells: [], // 合并单后数据
// 字段层级分类
propertyLvObj: {
l1: ["data1", ...],
l2: [...],
l3: [...],
l4: [...]
},
}
},
mounted() {
this.getTableData()
},
methods: {
//获取表格数据
getTableData(){
// 这里调用接口
const res = await $https.getVerifyPlan()
if (res) {
this.tableData = res.records
this.getMergeCells(res.records)
}
},
getMergeCells(data) {
let column = this.$refs.xTable.getColumns()
this.mergeCells = []
this.tableData.forEach((row, _rowIndex) => {
column.forEach((column, index) => {
let r = this.spanMethod({ row, _rowIndex, column, data })
if (r) {
this.mergeCells.push({ ...r, row: _rowIndex, col: index })
}
})
})
},
// 通用行合并函数(将相同多列数据合并为一行)
/**
* 思路 根据相邻行对应id 相同 才合并 需要注意的是 数据返回需要后端排序
*/
spanMethod({ row, _rowIndex, column, data }) {
// 需要合并的列
const fields = []
Object.keys(this.propertyLvObj).forEach((item) => {
fields.push(...this.propertyLvObj[item])
})
const cellValue = row[column.property] // 当前行数据的值
if (fields.includes(column.property)) {
const prevRow = data[_rowIndex - 1] // 上一行数据
let nextRow = data[_rowIndex + 1] // 下一行数据
if (prevRow && fields.includes(column.property) && this.filterFields(row, prevRow, column.property)) {
return { rowspan: 0, colspan: 0 }
} else {
let countRowspan = 1
while (nextRow && fields.includes(column.property) && this.filterFields(row, nextRow, column.property)) {
nextRow = data[++countRowspan + _rowIndex]
}
if (countRowspan > 1) {
return { rowspan: countRowspan, colspan: 1 }
}
}
}
},
/**
* 特定的字段列 判断条件不一样
* 根据相邻行数据前面的 mergeId1、mergeId2 来判断是否相同
*/
filterFields(currRow, row, property) {
if (this.propertyLvObj["l1"].includes(property) && currRow["mergeId1"] === row["mergeId1"]) {
return true
}
if (this.propertyLvObj["l2"].includes(property) && currRow["mergeId2"] === row["mergeId2"]) {
return true
}
if (this.propertyLvObj["l3"].includes(property) && currRow["mergeId3"] === row["mergeId3"]) {
return true
}
if (this.propertyLvObj["l4"].includes(property) && currRow["mergeId4"] === row["mergeId4"]) {
return true
}
return false
},
}
}
</script>
这里重点说明下官网 vxetable3.0版本 的虚拟滚动和合并单元不能同时使用问题。官网说的不能同时使用合并方法使用的是自定义
span-method
合并方法。如果是数据量小不需要虚拟滚动建议使用。除此以外建议使用merge-cells