Vue动态多级表头、相同内容列合并

1、需求:

  • 构造动态表头(根据后台返回的具体内容,对表头进行增或者减)
  • 第一列内容相同进行合并

2、最终效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m0uZv0rx-1666665993521)(/Users/hanshuai/Desktop/image-20221025093502166.png)]

3、动态表头:

新建组件:
<template>
  <el-table-column :label="coloumnHeader.label" :prop="coloumnHeader.label">
    <template v-for="item in coloumnHeader.children">
      <tableColumn
        v-if="item.children && item.children.length"
        :key="item.id"
        :coloumn-header="item"
      />
      <el-table-column
        v-else
        :key="item.name"
        :label="item.label"
        :prop="item.prop"
      />
    </template>
  </el-table-column>
</template>
<script>
export default {
  name: 'TableColumn',
  props: {
    coloumnHeader: {
      type: Object,
      required: true
    }
  }
}
</script>
主界面引用:

表头数据我是在后端做好之后传到前端的,对应这个格式,可以实现增加或减少。

<template>
  <div class="app-container">
    <el-table :data="tableData" style="width: 100%" :span-method="objectSpanMethod" border show-summary>
      <template v-for="item in tableConfig">
        <table-column
          v-if="item.children && item.children.length"
          :key="item.id"
          :coloumn-header="item"
        />
        <el-table-column
          v-else
          :key="item.id + 1"
          :label="item.label"
          :prop="item.prop"
        />
      </template>
    </el-table>
  </div>
</template>
<script>
// 引入api
import TableColumn from '@/views/finance/components/Table.vue'
export default {
  // 定义页面数据
  components: { Treeselect, DynamicTable, TableColumn },
  data() {
    return {
      // 表数据
      tableData: [],
      // 表头数据
      tableConfig: [
            {
                "id": 2, 
                "label": "停车场名称", 
                "prop": "parkName", 
                "children": null
            }, 
            {
                "id": 85, 
                "label": "日期", 
                "prop": "date", 
                "children": null
            }, 
            {
                "id": 0, 
                "label": "微信支付", 
                "prop": "0", 
                "children": [
                    {
                        "id": 12, 
                        "label": "交易笔数", 
                        "prop": "count0", 
                        "children": null
                    }, 
                    {
                        "id": 89, 
                        "label": "交易金额", 
                        "prop": "money0", 
                        "children": null
                    }
                ]
            }, 
            {
                "id": 1, 
                "label": "支付宝支付", 
                "prop": "1", 
                "children": [
                    {
                        "id": 40, 
                        "label": "交易笔数", 
                        "prop": "count1", 
                        "children": null
                    }, 
                    {
                        "id": 61, 
                        "label": "交易金额", 
                        "prop": "money1", 
                        "children": null
                    }
                ]
            }
        ],
    }
  }
}
</script>

4、合并内容相同列:

element ui 官网提供了合并的方法 :span-method="objectSpanMethod"

官方文档:

​ 通过给table传入span-method方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row当前列column当前行号rowIndex、**当前列号columnIndex **四个属性。该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan(跨几行),第二个元素代表colspan(跨几列)。也可以返回一个键名为rowspancolspan的对象。

具体实现:

objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  if (columnIndex === 0) {
    // this.tableData  修改
    // [7, 0, 0, 0, 0, 0, 0]
    const _row = (this.filterData(this.tableData).one)[rowIndex]
    const _col = _row > 0 ? 1 : 0
    return {
      rowspan: _row,
      colspan: _col
    }
  }
},

过滤数据:(判断第一列内容是否相同 返回数组 由objectSpanMethod 进行控制是否合并)

filterData(arr) {
  const spanOneArr = []
  let concatOne = 0
  arr.forEach((item, index) => {
    if (index === 0) {
      spanOneArr.push(1)
    } else {
      if (item.parkName === arr[index - 1].parkName) { // 第一列需合并相同内容的判断条件
        spanOneArr[concatOne] += 1 // 跨行数+1
        spanOneArr.push(0) // 数组后边补0
      } else {
        spanOneArr.push(1)
        concatOne = index
      }
    }
  })
  return {
    one: spanOneArr
  }
},

5、完整代码

<template>
  <div class="app-container">
    <el-table
      :data="tableData"
      style="width: 100%"
      :span-method="objectSpanMethod"
      border
      show-summary
    >
      <template v-for="item in tableConfig">
        <table-column
          v-if="item.children && item.children.length"
          :key="item.id"
          :coloumn-header="item"
        />
        <el-table-column
          v-else
          :key="item.id + 1"
          :label="item.label"
          :prop="item.prop"
        />
      </template>
    </el-table>
  </div>
</template>
<script>
import TableColumn from '@/views/finance/components/Table.vue'
export default {
  // 定义页面数据
  components: { TableColumn },
  data() {
    return {
      // 表数据
      tableData: [],
      // 表头数据
      tableConfig: [],
    }
  },
  // 勾子
  created() {
    this.initTable()
  },
  // 方法
  methods: {
    filterData(arr) {
      const spanOneArr = []
      let concatOne = 0
      arr.forEach((item, index) => {
        if (index === 0) {
          spanOneArr.push(1)
        } else {
          if (item.parkName === arr[index - 1].parkName) { // 第一列需合并相同内容的判断条件
            spanOneArr[concatOne] += 1 // 跨行数+1
            spanOneArr.push(0) // 数组后边补0
          } else {
            spanOneArr.push(1)
            concatOne = index
          }
        }
      })
      return {
        one: spanOneArr
      }
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        // this.tableData  修改
        // [7, 0, 0, 0, 0, 0, 0]
        const _row = (this.filterData(this.tableData).one)[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },
    
    // 初始化表格数据
    initTable() {
      //向后端请求表头数据、表格数据
    },  
  }
}
</script>
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值