做一个动态合并的table表格, 如下图
1.首先定义需要合并的字段及合并后的对象
data(){return {mergeFields: ['name', 'amount3'],mergeObj: {}}
}
2.分配合并项函数, data为数据源
//获取合并序号getSpanArr(data = []) {this.mergeFields.forEach(key => {// 用来记录合并行的起始位置let count = 0// 记录每一列的合并信息this.mergeObj[key] = []data.forEach((item, index) => {// 第一行直接 push 一个 1if (!index) {this.mergeObj[key].push(1)return}// 判断当前行是否与上一行其值相等 // 如果相等在count记录的位置其值+1 // 表示当前行需要合并 并添加一个 0 占位if (item[key] === data[index - 1][key]) {this.mergeObj[key][count] += 1this.mergeObj[key].push(0)return}// 如果当前行和上一行其值不相等 记录当前位置count = index // 重新push一个1this.mergeObj[key].push(1) })})},//合并行objectSpanMethod({ row, column, rowIndex, columnIndex }) {if (!this.mergeFields.includes(column.property)) return// 判断其值是不是为0if (this.mergeObj[column.property][rowIndex]) {return [this.mergeObj[column.property][rowIndex], 1]}// 如果为0则为需要合并的行return [0, 0]},
3.数据内容改变时函数
//改变百分比触发changeVal(val, row, idx) {//找到一级相同项let alikeList = this.tableData.filter(it => it.name == row.name)//汇总let allPercent = alikeList.reduce((acc, curr) => {return acc + curr.amount2}, 0)//改变每一项let list = JSON.parse(JSON.stringify(this.tableData))list.forEach(it => {if (it.name == row.name) {it.amount3 = allPercent}})//先分配需要合并项this.getSpanArr(list)this.$nextTick(() => {this.tableData = JSON.parse(JSON.stringify(list))})}
4.完整代码
<template><div class="wokeRate"><el-table :data="tableData" :span-method="objectSpanMethod" :border="true" size="small"><el-table-column v-for="item in fields" :key="item.key" :prop="item.key" :label="item.label":width="item.width"><template slot-scope="scope"><div class="it" v-if="item.type == 'text'">{{ scope.row[item.key] }}</div><div class="it" v-if="item.type == 'input'"><el-input-number size="mini" v-model="scope.row[item.key]" :placeholder="`请输入${item.label}`"@change="e => changeVal(e, scope.row, scope.$index)"></el-input-number></div></template></el-table-column></el-table></div>
</template><script>
export default {name: 'DfcvDtmsVueWokeRate',data() {return {mergeFields: ['name', 'amount3'],mergeObj: {},tableData: [{name: '维保',amount1: '维保',amount2: 0,amount3: 0}, {name: '等待样品',amount1: '等待样机',amount2: 0,amount3: 0}, {name: '等待样品',amount1: '等待样件',amount2: 0,amount3: 0},{name: '无任务',amount1: '无任务',amount2: 0,amount3: 0}],fields: [{label: '一级',key: 'name',type: 'text'},{label: '二级',key: 'amount1',type: 'text'},{label: '百分比(%)',key: 'amount2',type: 'input'},{label: '汇总(%)',key: 'amount3',type: 'text'}]}},mounted() {this.getSpanArr(this.tableData)},methods: {//获取合并序号getSpanArr(data = []) {this.mergeFields.forEach(key => {// 用来记录需要合并行的起始位置let count = 0// 记录每一列的合并信息this.mergeObj[key] = []data.forEach((item, index) => {// 第一行直接 push 一个 1if (!index) {this.mergeObj[key].push(1)return}// 判断当前行是否与上一行其值相等 // 如果相等在count记录的位置其值+1 // 表示当前行需要合并 并添加一个 0 占位if (item[key] === data[index - 1][key]) {this.mergeObj[key][count] += 1this.mergeObj[key].push(0)return}// 如果当前行和上一行其值不相等 记录当前位置count = index// 重新push一个 1this.mergeObj[key].push(1)})})},//合并行objectSpanMethod({ row, column, rowIndex, columnIndex }) {if (!this.mergeFields.includes(column.property)) return// 判断其值是不是为0if (this.mergeObj[column.property][rowIndex]) {return [this.mergeObj[column.property][rowIndex], 1]}// 如果为0则为需要合并的行return [0, 0]},//改变百分比触发changeVal(val, row, idx) {//找到一级相同项let alikeList = this.tableData.filter(it => it.name == row.name)//汇总let allPercent = alikeList.reduce((acc, curr) => {return acc + curr.amount2}, 0)//改变每一项let list = JSON.parse(JSON.stringify(this.tableData))list.forEach(it => {if (it.name == row.name) {it.amount3 = allPercent}})//先分配需要合并项this.getSpanArr(list)this.$nextTick(() => {this.tableData = JSON.parse(JSON.stringify(list))})}}
}
</script><style lang="scss" scoped>
.wokeRate {width: 100%;padding: 20px 0;.el-table {margin-top: 20px;}
}
</style>
elementPlus一样使用