1、接到一个比较奇怪的需求就是表单里面有相同的数据就需要合并单元格,这样看起来比较哇塞!但是数据不规定,有可能是2 合并有可能是3个合并
直接上代码html
<template>
<el-table ref="table" :data="tableData" border style="width: 80%;" :span-method="mergeCols" @row-click="onRowClick"
@selection-change="handleSelectionChange">
<!-- 列表公共列 -->
<el-table-column v-if="showSelection" type="selection" align="center" width="50" />
<el-table-column type="index" align="center" width="50" label="序号" />
<template v-for="colConfig in customColConfigs">
<!--无需合并的列信息-->
<el-table-column v-if="colConfig.type === 'label' && !colConfig.children" :key="colConfig.prop"
:prop="colConfig.prop" :align="colConfig.align" :label="colConfig.label" :min-width="colConfig.width"
:formatter="colConfig.formatter" :show-overflow-tooltip="colConfig.showOverflowTooltip" />
<!--需合并的列信息-->
<el-table-column v-else-if="colConfig.type === 'label' && colConfig.children" :key="colConfig.label"
:align="colConfig.align" :label="colConfig.label" :min-width="colConfig.width">
<template v-for="children in colConfig.children">
<el-table-column :key="children.prop" :prop="children.prop" :align="children.align" :label="children.label"
:min-width="children.width" :show-overflow-tooltip="children.showOverflowTooltip" />
</template>
</el-table-column>
<!--自定义的列信息-->
<el-table-column v-else-if="colConfig.type !== 'label'" :key="colConfig.prop" :prop="colConfig.prop"
:align="colConfig.align" :label="colConfig.label" :min-width="colConfig.width">
<template slot-scope="scope">
<el-input v-if="colConfig.type === 'input'" v-model="scope.row[colConfig.prop]"
:disabled="colConfig.disabled" />
</template>
</el-table-column>
</template>
</el-table>
</template>
js部分
<script>
export default {
props: {
tableData: {
type: Array,
required: true
},
colConfigs: {
required: true,
type: Array
},
showSelection: {
type: Boolean,
default: true
},
mergeColumns: {
type: Array,
default() {
return []
}
}
},
data() {
return {
multipleSelection: [],
customColConfigs: {},
tableMergeData: []
}
},
mounted() {
this.customColConfigs = this.colConfigs
if (this.mergeColumns.length > 0) {
this.$nextTick(() => {
this.generateTableMergeData()
})
}
},
methods: {
/**
* 表格行点击事件
* @param row 行对象
*/
onRowClick(row) {
this.$refs.table.toggleRowSelection(row)
},
/**
* 表格多选框选中事件
* @param val 选中的行数据信息
*/
handleSelectionChange(val) {
this.multipleSelection = val
},
/**
* element表格合并方法
* @param rowIndex 行坐标
* @param columnIndex 列坐标
* @returns {*} 单元格坐标信息
*/
mergeCols({ rowIndex, columnIndex }) {
const key = columnIndex + '_' + rowIndex
if (this.tableMergeData[key]) {
return this.tableMergeData[key]
}
},
/**
* 生成合并表格信息
*/
generateTableMergeData() {
// 遍历表格中需要合并的所有单元格
for (let i = 0; i < this.tableData.length; i++) {
for (let j = 0; j < this.mergeColumns.length; j++) {
// 初始化行、列坐标信息
let rowIndex = 1
let columnIndex = 1
// 比较横坐标左方的第一个元素
if (j > 0 && this.tableData[i][this.mergeColumns[j]['name']] === this.tableData[i][this.mergeColumns[j - 1]['name']]) {
columnIndex = 0
}
// 比较纵坐标上方的第一个元素
if (i > 0 && this.tableData[i][this.mergeColumns[j]['name']] === this.tableData[i - 1][this.mergeColumns[j]['name']]) {
rowIndex = 0
}
// 比较横坐标右方元素
if (columnIndex > 0) {
columnIndex = this.calculateColumnIndex(this.tableData[i], j, j + 1, 1, this.mergeColumns.length)
}
// 比较纵坐标下方元素
if (rowIndex > 0) {
rowIndex = this.calculateRowIndex(this.tableData, i, i + 1, 1, this.mergeColumns[j]['name'])
}
const key = this.mergeColumns[j]['index'] + '_' + i
this.tableMergeData[key] = [rowIndex, columnIndex]
}
}
},
/**
* 计算列坐标信息
* @param data 单元格所在行数据
* @param index 当前下标
* @param nextIndex 下一个元素坐标
* @param count 相同内容的数量
* @param maxLength 当前行的列总数
* @returns {*}
*/
calculateColumnIndex(data, index, nextIndex, count, maxLength) {
// 比较当前单元格中的数据与同一行之后的单元格是否相同
if (nextIndex < maxLength && data[this.mergeColumns[index]['name']] === data[this.mergeColumns[nextIndex]['name']]) {
return this.calculateColumnIndex(data, index, ++nextIndex, ++count, maxLength)
}
return count
},
/**
* 计算行坐标信息
* @param data 单元格所在行数据
* @param index 当前下标
* @param nextIndex 下一个元素坐标
* @param count 相同内容的数量
* @param name 数据的key
* @returns {*}
*/
calculateRowIndex(data, index, nextIndex, count, name) {
// 比较当前单元格中的数据与同一列之后的单元格是否相同
if (nextIndex < data.length && data[index][name] === data[nextIndex][name]) {
return this.calculateRowIndex(data, index, ++nextIndex, ++count, name)
}
return count
}
}
}
</script>