el-table 多表头+跨行跨列案例

效果:

代码:

index.vue

html 复制代码
<template>
  <div class="my-table">
    <el-table
      v-loading="table.loading"
      :data="table.data"
      border
      size="mini"
      :header-cell-style="headerCellStyle"
      :span-method="spanMethod"
    >
      <!-- 使用递归组件渲染表头 -->
      <myColumn
        v-for="(item, index) in table.header"
        :key="index"
        :header="item"
      />
    </el-table>
  </div>
</template>

<script>
// 引入组件
import myColumn from "./my-column.vue";

export default {
  name: "Test1",
  components: { myColumn },
  data() {
    return {
      table: {
        loading: false,
        header: [],
        data: [],
      },
    };
  },
  computed: {},
  created() {},
  mounted() {
    // 表头
    this.table.header = [
      {
        prop: "date",
        label: "月份",
        width: "100px",
        children: [],
        fixed: false,
      },
      {
        prop: "project1",
        label: "",
        width: "100px",
        children: [],
      },
      {
        prop: "project2",
        label: "项目",
        width: "100px",
        position: "111",
        children: [],
      },
      {
        prop: "index",
        label: "序号",
        width: "50px",
        children: [],
      },
      {
        prop: "deliveryInfo",
        label: "线下合计",
        width: "560px",
        children: [
          {
            prop: "name",
            label: "2024",
            width: "80px",
            children: [
              {
                prop: "name",
                label: "金额",
                width: "80px",
              },
              {
                prop: "name",
                label: "%",
                width: "80px",
                children: [],
              },
            ],
          },
          {
            prop: "name",
            label: "2023",
            width: "80px",
            children: [
              {
                prop: "name",
                label: "金额",
                width: "80px",
              },
              {
                prop: "name",
                label: "%",
                width: "80px",
                children: [],
              },
            ],
          },
          {
            prop: "name",
            label: "增长",
            width: "80px",
            children: [
              {
                prop: "name1",
                label: "金额",
                width: "80px",
              },
              {
                prop: "name",
                label: "%",
                width: "80px",
                children: [],
              },
            ],
          },
        ],
      },
      {
        prop: "deliveryInfo",
        label: "东北",
        width: "560px",
        children: [
          {
            prop: "name",
            label: "2024",
            width: "80px",
            children: [
              {
                prop: "name",
                label: "金额",
                width: "80px",
              },
              {
                prop: "name",
                label: "%",
                width: "80px",
                children: [],
              },
            ],
          },
          {
            prop: "name",
            label: "2023",
            width: "80px",
            children: [
              {
                prop: "name",
                label: "金额",
                width: "80px",
              },
              {
                prop: "name",
                label: "%",
                width: "80px",
                children: [],
              },
            ],
          },
          {
            prop: "name",
            label: "增长",
            width: "80px",
            children: [
              {
                prop: "name",
                label: "金额",
                width: "80px",
              },
              {
                prop: "name",
                label: "%",
                width: "80px",
                children: [],
              },
            ],
          },
        ],
      },
    ];
    // 数据
    this.table.data = [
      {
        date: "2016-05-03",
        project1: "数量",
        project2: "鞋",
        province: "上海",
        city: "普陀区",
        address: "上海市普陀区金沙江路 1518 弄",
        index: 0,
        name1: 10086,
      },
      {
        date: "2016-05-02",
        project1: "数量",
        project2: "包服配",
        province: "上海",
        city: "普陀区",
        address: "上海市普陀区金沙江路 1518 弄",
        index: 1,
      },
      {
        date: "2016-05-04",
        name: "王小虎",
        project1: "收入",
        project2: "实数收入",
        province: "上海",
        city: "普陀区",
        address: "上海市普陀区金沙江路 1518 弄",
        zip: 200333,
      },
      {
        date: "2016-05-01",
        name: "王小虎",
        project1: "收入",
        project2: "无税收入",
        province: "上海",
        city: "普陀区",
        address: "上海市普陀区金沙江路 1518 弄",
        zip: 200333,
      },
      {
        date: "2016-05-08",
        name: "王小虎",
        project1: "收入",
        project2: "有税收入",
        province: "上海",
        city: "普陀区",
        address: "上海市普陀区金沙江路 1518 弄",
        zip: 200333,
      },
      {
        date: "2016-05-06",
        name: "王小虎",
        project1: "附加税金",
        project2: "附加税金",
        province: "上海",
        city: "普陀区",
        address: "上海市普陀区金沙江路 1518 弄",
        zip: 200333,
      },
      {
        date: "2016-05-07",
        name: "王小虎",
        project1: "附加税金1",
        project2: "附加税金2",
        province: "上海",
        city: "普陀区",
        address: "上海市普陀区金沙江路 1518 弄",
        zip: 200333,
      },
    ];
  },
  methods: {
    spanMethod({ row, column, rowIndex, columnIndex }) {
      // const rowData = Object.values(row);
      // if ((rowData[1] === rowData[2])) { // 根据实际需求变更
      if ((row['project1'] === row['project2'])) { // 根据实际需求变更
        // 跨列数据相同合并
        if (columnIndex === 1) {
          return [1, 2];
        } else if (columnIndex === 2) {
          return [0, 0]
        }
      } else {
        if (columnIndex === 1) {
          // 列数据相同合并
          const currentValue = row[column.property];
          const preRow = this.table.data[rowIndex - 1];
          const preValue = preRow ? preRow[column.property] : null;
          if (currentValue === preValue) {
            return [0, 0]
          } else {
            let rowspan = 1;
            for (let i = rowIndex + 1; i < this.table.data.length; i++) {
              const nextRow = this.table.data[i]
              const nextValue = nextRow[column.property]
              if (nextValue === currentValue) {
                rowspan++;
              } else {
                break;
              }
            }
            return [rowspan, 1];
          }
        }
      }
    },
    headerCellStyle({ row, column, rowIndex, columnIndex }) {
      let base = { "background": "#4389f94d",color: "#333" };
      if (column.label === "") {
        // 隐藏
        return { display: "none" };
      }
      if (column.property === "project2") { // 根据实际需求变更
        this.$nextTick(() => {
          if (document.getElementsByClassName(column.id).length !== 0) {
            document
              .getElementsByClassName(column.id)[0]
              .setAttribute("colSpan", 2); // 根据实际需求变更
          }
        });
      }
      return base;
    },
  },
};
</script>

<style lang="scss" scoped></style>

my-column.vue

html 复制代码
<template>
  <el-table-column
    :prop="header.prop"
    :label="header.label"
    :fixed="header.fixed"
    :min-width="header.width"
    align="center"
    show-overflow-tooltip
  >
    <template v-if="header.children && header.children.length">
      <myColumn v-for="(child, index) in header.children" :key="index" :header="child" />
    </template>
  </el-table-column>
</template>

<script>
export default {
  name: "myColumn",
  components: {},
  props: {
    header: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {};
  },
  mounted() {},
  methods: {},
};
</script>

<style lang="scss" scoped></style>

附加:index.html模版

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>demo</title>
    <!-- 引入样式 -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/vue@2/dist/vue.js"></script>
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  </head>

  <body>
    <div id="app">
      <div class="my-table">
        <el-table
          v-loading="table.loading"
          :data="table.data"
          border
          size="mini"
          :header-cell-style="headerCellStyle"
          :span-method="spanMethod"
        >
          <!-- 使用递归组件渲染表头 -->
          <mycolumn
            v-for="(item, index) in table.header"
            :key="index"
            :header="item"
          />
        </el-table>
      </div>
    </div>

    <script type="text/javascript">
      //定义组件
      Vue.component("mycolumn", {
        props: {
          header: {
            type: Object,
            required: true,
          },
        },
        template: `<el-table-column :prop="header.prop" :label="header.label" :fixed="header.fixed" :min-width="header.width" align="center" show-overflow-tooltip>
        <template v-if="header.children && header.children.length">
          <mycolumn v-for="(child, index) in header.children" :key="index" :header="child" />
        </template>
      </el-table-column>`,
      });

      var vm = new Vue({
        el: "#app",
        data() {
          return {
            table: {
              loading: false,
              header: [],
              data: [],
            },
          };
        },
        mounted() {
          // 表头
          this.table.header = [
            {
              prop: "date",
              label: "月份",
              width: "100px",
              children: [],
              fixed: false,
            },
            {
              prop: "project1",
              label: "",
              width: "100px",
              children: [],
            },
            {
              prop: "project2",
              label: "项目",
              width: "100px",
              position: "111",
              children: [],
            },
            {
              prop: "index",
              label: "序号",
              width: "50px",
              children: [],
            },
            {
              prop: "deliveryInfo",
              label: "线下合计",
              width: "560px",
              children: [
                {
                  prop: "name",
                  label: "2024",
                  width: "80px",
                  children: [
                    {
                      prop: "name",
                      label: "金额",
                      width: "80px",
                    },
                    {
                      prop: "name",
                      label: "%",
                      width: "80px",
                      children: [],
                    },
                  ],
                },
                {
                  prop: "name",
                  label: "2023",
                  width: "80px",
                  children: [
                    {
                      prop: "name",
                      label: "金额",
                      width: "80px",
                    },
                    {
                      prop: "name",
                      label: "%",
                      width: "80px",
                      children: [],
                    },
                  ],
                },
                {
                  prop: "name",
                  label: "增长",
                  width: "80px",
                  children: [
                    {
                      prop: "name1",
                      label: "金额",
                      width: "80px",
                    },
                    {
                      prop: "name",
                      label: "%",
                      width: "80px",
                      children: [],
                    },
                  ],
                },
              ],
            },
            {
              prop: "deliveryInfo",
              label: "东北",
              width: "560px",
              children: [
                {
                  prop: "name",
                  label: "2024",
                  width: "80px",
                  children: [
                    {
                      prop: "name",
                      label: "金额",
                      width: "80px",
                    },
                    {
                      prop: "name",
                      label: "%",
                      width: "80px",
                      children: [],
                    },
                  ],
                },
                {
                  prop: "name",
                  label: "2023",
                  width: "80px",
                  children: [
                    {
                      prop: "name",
                      label: "金额",
                      width: "80px",
                    },
                    {
                      prop: "name",
                      label: "%",
                      width: "80px",
                      children: [],
                    },
                  ],
                },
                {
                  prop: "name",
                  label: "增长",
                  width: "80px",
                  children: [
                    {
                      prop: "name",
                      label: "金额",
                      width: "80px",
                    },
                    {
                      prop: "name",
                      label: "%",
                      width: "80px",
                      children: [],
                    },
                  ],
                },
              ],
            },
          ];
          // 数据
          this.table.data = [
            {
              date: "2016-05-03",
              project1: "数量",
              project2: "鞋",
              province: "上海",
              city: "普陀区",
              address: "上海市普陀区金沙江路 1518 弄",
              index: 0,
              name1: 10086,
            },
            {
              date: "2016-05-02",
              project1: "数量",
              project2: "包服配",
              province: "上海",
              city: "普陀区",
              address: "上海市普陀区金沙江路 1518 弄",
              index: 1,
            },
            {
              date: "2016-05-04",
              name: "王小虎",
              project1: "数量",
              project2: "实数收入",
              province: "上海",
              city: "普陀区",
              address: "上海市普陀区金沙江路 1518 弄",
              zip: 200333,
            },
            {
              date: "2016-05-01",
              name: "王小虎",
              project1: "收入",
              project2: "无税收入",
              province: "上海",
              city: "普陀区",
              address: "上海市普陀区金沙江路 1518 弄",
              zip: 200333,
            },
            {
              date: "2016-05-08",
              name: "王小虎",
              province: "上海",
              city: "普陀区",
              address: "上海市普陀区金沙江路 1518 弄",
              zip: 200333,
            },
            {
              date: "2016-05-06",
              name: "王小虎",
              province: "上海",
              city: "普陀区",
              address: "上海市普陀区金沙江路 1518 弄",
              zip: 200333,
            },
            {
              date: "2016-05-07",
              name: "王小虎",
              province: "上海",
              city: "普陀区",
              address: "上海市普陀区金沙江路 1518 弄",
              zip: 200333,
            },
          ];
        },
        methods: {
          spanMethod({ row, column, rowIndex, columnIndex }) {
            // const rowData = Object.values(row);
            // if ((rowData[1] === rowData[2])) { // 根据实际需求变更
            if (row["project1"] === row["project2"]) {
              // 根据实际需求变更
              // 跨列数据相同合并
              if (columnIndex === 1) {
                return [1, 2];
              } else if (columnIndex === 2) {
                return [0, 0];
              }
            } else {
              if (columnIndex === 1) {
                // 列数据相同合并
                const currentValue = row[column.property];
                const preRow = this.table.data[rowIndex - 1];
                const preValue = preRow ? preRow[column.property] : null;
                if (currentValue === preValue) {
                  return [0, 0];
                } else {
                  let rowspan = 1;
                  for (let i = rowIndex + 1; i < this.table.data.length; i++) {
                    const nextRow = this.table.data[i];
                    const nextValue = nextRow[column.property];
                    if (nextValue === currentValue) {
                      rowspan++;
                    } else {
                      break;
                    }
                  }
                  return [rowspan, 1];
                }
              }
            }
          },
          headerCellStyle({ row, column, rowIndex, columnIndex }) {
            let base = { background: "#4389f94d", color: "#333" };
            if (column.label === "") {
              // 隐藏
              return { display: "none" };
            }
            if (column.property === "project2") {
              // 根据实际需求变更
              this.$nextTick(() => {
                if (document.getElementsByClassName(column.id).length !== 0) {
                  document
                    .getElementsByClassName(column.id)[0]
                    .setAttribute("colSpan", 2); // 根据实际需求变更
                }
              });
            }
            return base;
          },
        },
      });
    </script>
  </body>
</html>
相关推荐
放逐者-保持本心,方可放逐2 分钟前
vue.config.js 简介 及 实例
前端·javascript·vue.js
落日弥漫的橘_31 分钟前
js 数组方法总结
前端·javascript
tester Jeffky38 分钟前
深入理解NPM:Node.js的包管理器
javascript·npm·node.js
余生H1 小时前
前端的Python入门指南(完):错误和异常处理策略及最佳实践
开发语言·前端·javascript·python
你的牧游哥1 小时前
Mac上使用ln指令创建软链接、硬链接
开发语言·前端·javascript
小兔崽子去哪了1 小时前
海康摄像头 web 对接
前端·vue.js·html
&活在当下&1 小时前
Element plus 下拉框组件选中一个选项后显示的是 value 而不是 label
前端·javascript·vue3·element plus
zzy_juheng1 小时前
弹出框(Dialog)简易使用指南
前端
Hilaku1 小时前
手写 Proxy API:从基础到实战
前端
蜂鸟视图fengmap2 小时前
蜂鸟云平台 JavaScript SDK 与微信小程序 SDK v3.1.5 更新分析
开发语言·javascript·微信小程序·蜂鸟云平台·javascript sdk·微信小程序sdk·地图开发者