做一個動態合并的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一樣使用