vue elementui 动态表头、表头合并、合并行、合并列、行根据某字段内容一致的进行合并、表格列展开收起功能

news2024/11/18 7:32:10

效果图:
在这里插入图片描述

1、表头第1、2列合并

在这里插入图片描述

第一种写法(普通表头):

<el-table
      ref="main"
      :data="tableData"
      border
      :header-cell-style="headerStyle"
      style="width: 100%;">
      <el-table-column align="center" width="40" label="年级" fixed prop="nj" />
      <el-table-column align="center" width="80" label="班级" fixed prop="bj" />
</el-table>
methods: {
    headerStyle({ row, column, rowIndex, columnIndex }) {
      const comStyle = {
        backgroundColor: "#4095e5",
        color: "#fff",
        fontSize: "500",
      };
      if (rowIndex === 0) {
        row[0].colSpan = 0; // 将表头第一列和第二列合并,内容展示为第二列的内容
        row[1].colSpan = 2;
        if (columnIndex === 0) { // 将表头第一列隐藏
          return {
            display: "none",
            ...comStyle,
          };
        }
      }
      return comStyle;
    },
}

第2种写法(二级表头):

<el-table
      ref="main"
      :data="tableData"
      border
      :header-cell-style="headerStyle"
      style="width: 100%;">

      <el-table-column align="center" label="班级" width="120">
        <el-table-column align="center" width="40" prop="nj" />
        <el-table-column align="center" width="80" prop="bj" />
      </el-table-column>
</el-table>
headerStyle({ row, column, rowIndex, columnIndex }) {
      const comStyle = {
        backgroundColor: "#4095e5",
        color: "#fff",
        fontSize: "500",
      };
      // 1.1 让第0行的第0列跨2行
      if (rowIndex === 0 && columnIndex === 0) {
        this.$nextTick(() => {
          document
            .getElementsByClassName(column.id)[0]
            .setAttribute("rowSpan", 2);
          return comStyle;
        });
      }
      // 1.2 被覆盖的进行隐藏
      if (rowIndex === 1 && (columnIndex == 0 || columnIndex == 1)) {
        return {
          display: "none",
          ...comStyle,
        };
      }
      return comStyle;
    },

2、行根据某字段内容一致的进行合并

在这里插入图片描述
给表格增加属性:span-method="spanMethod"
在这里插入图片描述

spanMethod({ row, column, rowIndex, columnIndex }) {
      // console.log('row', row, 'column', column, 'rowIndex', rowIndex, 'columnIndex', columnIndex);
      //定义需要合并的列字段,有哪些列需要合并,就自定义添加字段即可
      const fields = ['nj']
      // 当前行的数据
      const cellValue = row[column.property]
      if (rowIndex == 0) { // 实现表头下面第一行数据,第一列合计展示时2列合并
          if (columnIndex === 0) {
            return {rowspan: 1, colspan: 0} // 隐藏表头下面第一行的第一列
          }
          if (columnIndex === 1) {
            return {rowspan: 1, colspan: 2} // 将表头下面第一行的第一列和第二列合并
          }
        }

        // 判断只合并定义字段的列数据
        if (cellValue && fields.includes(column.property)) {
          const prevRow = this.tableData[rowIndex - 1] //上一行数据
          let nextRow = this.tableData[rowIndex + 1] //下一行数据
          // 当上一行的数据等于当前行数据时,当前行单元格隐藏
          if (prevRow && prevRow[column.property] === cellValue) {
            return { rowspan: 0, colspan: 0 }
          } else {
            // 反之,则循环判断若下一行数据等于当前行数据,则当前行开始进行合并单元格
            let countRowspan = 1 //用于合并计数多少单元格
            while (nextRow && nextRow[column.property] === cellValue) {
              nextRow = this.tableData[++countRowspan + rowIndex]
            }
            if (countRowspan > 1) {
              return { rowspan: countRowspan, colspan: 1 }
            }
          }
        }
    },

3、完整示例代码

在这里插入图片描述
在这里插入图片描述

<template>
  <div class="page-wrapper">
    <div class="search-wrapper">
      <el-row type="flex" justify="space-between">
        <div class="search-item width-31">
          <el-radio-group v-model="type">
            <el-radio :label="1">按班级汇总</el-radio>
            <el-radio :label="2">按年级汇总</el-radio>
          </el-radio-group>
        </div>
        <div class="search-item margin-right-0">
          <el-button size="mini" type="primary">查询</el-button>
          <el-button size="mini" type="primary" plain>重置</el-button>
          <el-button size="mini" type="primary" icon="el-icon-download" plain>导出</el-button>
        </div>
      </el-row>
    </div>
    <el-table
      ref="main"
      :data="tableData"
      border
      :header-cell-style="headerStyle"
      :span-method="spanMethod"
      style="width: 100%;">
      <template v-if="type === 1">
        <el-table-column align="center" width="40" label="年级" fixed prop="nj" />
        <el-table-column align="center" width="80" label="班级" fixed prop="bj" />
      </template>
      <template v-if="type === 2">
        <el-table-column align="center" width="100" label="年级" fixed prop="type" />
      </template>
      <el-table-column align="center" label="人数">
        <el-table-column align="center" label="" prop="num1" />
        <el-table-column align="center" label="" prop="money1" />
      </el-table-column>
      <el-table-column align="center" width="160" prop="num2">
        <template slot="header">
          <div class="expand-header-wrapper">
            <span class="title">姓名</span>
            <span class="btn" @click="showColumn('open1')">{{!open1 ? '+展开' : '-收起'}}</span>
          </div>
        </template>
      </el-table-column>
      <template v-if="open1">
        <el-table-column
          v-for="item in colunms1"
          :key="'姓名_' + item.name"
          :label="item.name"
          :label-class-name="'more-header'"
          align="center">
          <el-table-column
            v-for="citem in item.children"
            :key="'姓名_' + item.name + citem.name"
            :label="citem.name"
            :prop="citem.prop"
            :label-class-name="'more-header'"
            align="center"/>
        </el-table-column>
      </template>
      <el-table-column align="center" min-width="200" prop="num2">
        <template slot="header">
          <div class="expand-header-wrapper">
            <span class="title">地址</span>
            <span class="btn" @click="showColumn('open2')">{{!open2 ? '+展开' : '-收起'}}</span>
          </div>
        </template>
      </el-table-column>
      <template v-if="open2">
        <el-table-column
          v-for="item in colunms2"
          :key="'地址_' + item.name"
          :label="item.name"
          :label-class-name="'more-header'"
          align="center">
          <el-table-column
            v-for="citem in item.children"
            :key="'地址_' + item.name + citem.name"
            :label="citem.name"
            :prop="citem.prop"
            :label-class-name="'more-header'"
            align="center"/>
        </el-table-column>
      </template>
      <el-table-column align="center" width="100" prop="num2">
        <template slot="header">
          <div class="expand-header-wrapper">
            <span class="title">排名</span>
            <span class="btn" @click="showColumn('open3')">{{!open3 ? '+展开' : '-收起'}}</span>
          </div>
        </template>
        <template>
          <el-table-column align="center" label="年排" prop="num6" />
          <el-table-column align="center" label="班排" prop="money6" />
        </template>
      </el-table-column>
      <template v-if="open3">
        <el-table-column
          v-for="item in colunms3"
          :key="'排名_' + item.name"
          :label="item.name"
          :label-class-name="'more-header'"
          align="center">
          <el-table-column
            v-for="citem in item.children"
            :key="'排名_' + item.name + citem.name"
            :label="citem.name"
            :prop="citem.prop"
            :label-class-name="'more-header'"
            align="center"/>
        </el-table-column>
      </template>
    </el-table>
  </div>
</template>
<script>
export default {
  name: 'demo',
  data() {
    return {
      type: 1,
      tableData: [
        { nj: '合计', type: '合计', bj: '合计', num1: "1111", money1: "1111", num2: "1111", money2: "1111", sale: '111', num3: -2129, money3: "111", num4: "111", money4: "111", num5: "111", money5: "1111",},
        { nj: '初一', type: '初一', bj: "1班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初一', type: '初一', bj: "2班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初一', type: '初一', bj: "3班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初二', type: '初二', bj: "1班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初二', type: '初二', bj: "2班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初二', type: '初二', bj: "3班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初三', type: '初三', bj: "1班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初三', type: '初三', bj: "2班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '初三', type: '初三', bj: "3班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '高一', type: '高一', bj: "1班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '高一', type: '高一', bj: "2班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '高一', type: '高一', bj: "3班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '高二', type: '高二', bj: "1班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '高二', type: '高二', bj: "2班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
        { nj: '高三', type: '高三', bj: "1班", num1: "1", money1: "1", num2: "1", money2: "1", sale: '1', num3: "1", money3: "1", num4: "1", money4: "1", num5: "1", money5: "1",},
      ],
      open1: false,
      open2: false,
      open3: true,
      colunms1: [
        {
          name: "外形",
          children: [
            { name: "身高", prop: "num3" },
            { name: "体重", prop: "money3" },
          ],
        },
        {
          name: "发型",
          children: [
            { name: "颜色", prop: "num4" },
            { name: "长短", prop: "money4" },
          ],
        },
      ],
      colunms2: [
        {
          name: "省市",
          children: [
            { name: "省份", prop: "num3" },
            { name: "城市", prop: "money3" },
          ],
        },
        {
          name: "区域",
          children: [
            { name: "区域", prop: "num4" },
            { name: "街道", prop: "money4" },
          ],
        },
        {
          name: "村委",
          children: [
            { name: "村落", prop: "money5" },
            { name: "门牌", prop: "money5" },
          ],
        },
        {
          name: "人员情况",
          children: [
            { name: "兄弟", prop: "money5" },
            { name: "姐妹", prop: "money5" },
          ],
        },
      ],
      colunms3: [
        {
          name: "主科",
          children: [
            { name: "语文", prop: "num3" },
            { name: "数学", prop: "money3" },
            { name: "英语", prop: "money3" },
          ],
        },
        {
          name: "其他文科学科",
          children: [
            { name: "历史", prop: "num4" },
            { name: "政治", prop: "money4" },
            { name: "地理", prop: "money4" },
          ],
        },
        {
          name: "其他理科学科",
          children: [
            { name: "物理", prop: "num4" },
            { name: "生物", prop: "money4" },
            { name: "化学", prop: "money4" },
          ],
        },
      ],
    }
  },
  created() {},
  methods: {
    /** 表头合并控制 */
    headerStyle({ row, column, rowIndex, columnIndex }) {
      const comStyle = {
        backgroundColor: "#4095e5",
        color: "#fff",
        fontSize: "500",
      };
      /*
        // 1.1 让第0行的第0列跨2行
        if (rowIndex === 0 && columnIndex === 0) {
          this.$nextTick(() => {
            document
              .getElementsByClassName(column.id)[0]
              .setAttribute("rowSpan", 2);
            return comStyle;
          });
        }
        // 1.2 被覆盖的进行隐藏
        if (rowIndex === 1 && (columnIndex == 0 || columnIndex == 1)) {
          return {
            display: "none",
            ...comStyle,
          };
        } */
      if (this.type === 1 && rowIndex === 0) {
        row[0].colSpan = 0; // 将表头第一列和第二列合并,内容展示为第二列的内容
        row[1].colSpan = 2;
        if (columnIndex === 0) { // 将表头第一列隐藏
          return {
            display: "none",
            ...comStyle,
          };
        }
      }
      return comStyle;
    },
    /** 合并行、列 */
    spanMethod({ row, column, rowIndex, columnIndex }) {
      // console.log('row', row, 'column', column, 'rowIndex', rowIndex, 'columnIndex', columnIndex);
      //定义需要合并的列字段,有哪些列需要合并,就自定义添加字段即可
      let fields = []
      if (this.type === 1) {
        fields.push('nj')
      } else {
        fields.push('type')
      }
      // 当前行的数据
      const cellValue = row[column.property]
      if (this.type === 1 && rowIndex == 0) {
          if (columnIndex === 0) {
            return {rowspan: 1, colspan: 0} // 隐藏表头下面第一行的第一列
          }
          if (columnIndex === 1) {
            return {rowspan: 1, colspan: 2} // 将表头下面第一行的第一列和第二列合并
          }
        }

        // 判断只合并定义字段的列数据
        if (cellValue && fields.includes(column.property)) {
          const prevRow = this.tableData[rowIndex - 1] //上一行数据
          let nextRow = this.tableData[rowIndex + 1] //下一行数据
          // 当上一行的数据等于当前行数据时,当前行单元格隐藏
          if (prevRow && prevRow[column.property] === cellValue) {
            return { rowspan: 0, colspan: 0 }
          } else {
            // 反之,则循环判断若下一行数据等于当前行数据,则当前行开始进行合并单元格
            let countRowspan = 1 //用于合并计数多少单元格
            while (nextRow && nextRow[column.property] === cellValue) {
              nextRow = this.tableData[++countRowspan + rowIndex]
            }
            if (countRowspan > 1) {
              return { rowspan: countRowspan, colspan: 1 }
            }
          }
        }
    },
    /** 展开列 */
    showColumn(key) {
      this[key] = !this[key]
      this.$nextTick(() => {
        // 由于elementui框架问题,展开列后表格高度变小,需要重新布局、渲染表格
        this.$refs.main.doLayout();
      })
    },
  }
}
</script>
<style lang="scss" scoped>
@import '../static/styles/page.scss';

::v-deep .el-radio-group label {
  width: 100px !important;
}

.expand-header-wrapper {
  position: relative;
  .btn {
    position: absolute;
    right: 10px;
    color: #fefa83;
    text-decoration: underline;
    font-style: italic;
    cursor: pointer;
  }
}
::v-deep .el-table__header {
  .more-header {
    background: #cba43f !important;
  }
}

::v-deep .el-table__row:first-child .cell{
  color: #333;
  font-weight: 700;
  &:first-child {
    font-style: italic;
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1150455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微软服务器数据库 Navicat Premium 连接

需要固定IP&#xff0c;在服务器的网络里面加上。 需要打开SSL,入下图 只用打开&#xff0c;不用选择秘钥&#xff0c;证书等

Centos下用nodejs实现一个简单的web服务器

WebRTC是音视频直播中最常用的一个框架&#xff0c;在使用的过程中&#xff0c;我们就需要实现一个服务器端。本文以nodejs实现一个服务器为例&#xff0c;讲述一下在centos下如何用nodejs实现一个简单的web服务器。 一、安装nodejs 在linux环境下安装nodejs有多重方式&#x…

从 0 到 1 ,手把手教你编写《消息队列》项目(Java实现) —— 编写客户端

文章目录 一、设计核心类Connection 类Channel 类ConnectionFactory 类 二、代码编写Connection 类Connection 类Channel 类 一、设计核心类 Connection 类 Connection类有以下特点与功能 表示一个TCP连接该类持有 Socket对象可以写入请求,读取响应管理多个 Channel 对象 Ch…

万万没想到!| 三代宏病毒组研究还能这么干!

书接上回&#xff0c;我也是一个万万没想到啊&#xff0c;陈卫华&#xff0c;赵兴明老师的三代宏病毒组研究&#xff0c;居然让我追到续集了&#xff01; 前一回中&#xff0c;利用三代单分子测序技术&#xff0c;科研团队成功构建了中国人肠道噬菌体目录&#xff08;CHGV&…

云安全—K8S API Server 未授权访问

0x00 前言 master节点的核心就是api服务&#xff0c;k8s通过REST API来进行控制&#xff0c;在k8s中的一切都可以抽象成api对象&#xff0c;通过api的调用来进行资源调整&#xff0c;分配和操作。 通常情况下k8s的默认api服务是开启在8080端口&#xff0c;如果此接口存在未授…

【验证码系列】用逆向思维深度分析滑动验证码(含轨迹算法)

文章目录 1. 写在前面2. 抓包分析3. 接口分析4. 滑动验证码弹出分析5. 滑动验证分析6. 轨迹生成算法实现7. 生成W参数值算法 1. 写在前面 验证码是机器人防护&#xff08;即爬虫&#xff09;常用重要手段之一&#xff01;在爬虫这个领域内专精某一项&#xff08;验证码识别、JS…

七人拼团模式:颠覆你的购物观念,499元产品让你赚翻天!

七人拼团模式是一种创新的消费模式&#xff0c;通过聚集消费者的购买力&#xff0c;让消费者能够以更优惠的价格购买到优质的商品。下面我们以499元的产品为例&#xff0c;详细介绍七人拼团模式的玩法规则和收益计算。 玩法规则&#xff1a; 消费者购买499元的指定产品后&…

wireshark捕获DNS

DNS解析&#xff1a; 过滤项输入dns&#xff1a; dns查询报文 应答报文&#xff1a; 事务id相同&#xff0c;flag里 QR字段1&#xff0c;表示响应&#xff0c;answers rrs变成了2. 并且响应报文多了Answers 再具体一点&#xff0c;得到解析出的ip地址&#xff08;最底下的add…

write_edif 生成 AD9361 配置的自定义IP核

将AD9361配置文件设置为顶层 设置里&#xff1b; -mode out_of_context 替换文字 综合 导出 IP 核 write_edif -security_mode all D:/tops.edfD:/tops.edf write_verilog -mode synth_stub D:/tops_stub.vD:/tops_stub.v 调用 AD9361 IP 核

OpenAI将推出ChatGPT Plus会员新功能,有用户反馈将支持上传文件和多模态

&#x1f989; AI新闻 &#x1f680; OpenAI将推出ChatGPT Plus会员新功能&#xff0c;有用户反馈将支持上传文件和多模态 摘要&#xff1a;OpenAI为ChatGPT Plus会员推出了一些新功能&#xff0c;包括上传文件、处理文件和多模态支持。用户不再需要手动选择模式&#xff0c;…

视频直播与制作软件 Wirecast Pro mac中文版软件功能

Wirecast Pro mac是一款专业的视频直播和流媒体软件&#xff0c;由Telestream公司开发和发布&#xff0c;适用于各种场景&#xff0c;包括企业会议、体育赛事、音乐演出、教育培训等。 Wirecast Pro mac软件功能 支持多摄像头连接&#xff0c;实现多角度拍摄和切换。 可导入图片…

电脑文件夹怎么压缩?分享三个简单的方法!

为了节省存储空间和便于管理&#xff0c;压缩文件夹可以将多个文件或文件夹整合成一个压缩文件&#xff0c;从而节省存储空间。此外&#xff0c;压缩文件夹还可以方便地管理文件&#xff0c;那么电脑文件夹怎么压缩呢&#xff1f;一起来看看吧~ 一、电脑自带的压缩功能 1、找到…

虹科新闻 | 高性能超声波测距仪来袭,虹科与MaxBotix正式建立合作伙伴关系

近日&#xff0c;虹科与MaxBotix正式建立合作关系&#xff0c;将共同致力于提供高精度、工业级耐用性、功能先进和有防水保护的超声波传感器&#xff0c;重新定义距离测量技术。 虹科CEO陈秋苑表示&#xff1a;“我们非常自豪地宣布&#xff0c;与MaxBotix合作&#xff0c;为我…

在WEB应用使用MyBatis(使用MVC架构模式)

2023.10.30 本章将在web应用中使用MyBatis&#xff0c;实现一个银行转账的功能。整体架构采用MVC架构模式。 数据库表的初始化 环境的初始化配置 web.xml文件的配置&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"h…

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 第六章 muduo网络库简介

2010年3月作者写了一篇《学之者生&#xff0c;用之者死——ACE历史与简评》&#xff08;http://blog.csdn.net/Solstice/archive/2010/03/10/5364096.aspx&#xff0c;ACE是&#xff08;Adaptive Communication Environment&#xff09;是一个C编写的开源框架&#xff0c;用于开…

如何使用IP归属地查询API加强网络安全

引言 在当今数字化时代&#xff0c;网络安全对于个人和组织来说至关重要。恶意网络活动的威胁不断增加&#xff0c;因此采取有效的措施来加强网络安全至关重要。其中之一是利用IP归属地查询API。这个工具可以为您的网络安全策略提供宝贵的信息&#xff0c;帮助您更好地保护自己…

微软bing大声朗读文档或网页卡顿老是中断,用离线的huihui就很流畅但没那么自然

默认的xiaoxiao_online好听&#xff0c;但卡顿&#xff0c;朗读功能确实受到了网络状态的影响。 大概率是网络问题。

概念解析 | 动态非线性系统 VS 非线性系统 VS 线性系统

KaTeX parse error: \newcommand{\blue} attempting to redefine \blue; use \renewcommand 注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:动态非线性系统 VS 非线性系统 VS 线性系统。 概念解析 | 动态非线性系统 VS 非线性…

国产射频功率放大器技术指标有哪些内容

射频功率放大器是一种广泛应用于通信、雷达、卫星等领域的高频电子设备&#xff0c;其作用是将微弱的电磁信号放大到足以传输或检测的强度。射频功率放大器技术指标是衡量其性能优劣的重要标准&#xff0c;其主要内容包括以下几个方面。 频率范围&#xff1a;射频功率放大器需要…

接雨水 DP 双指针

力扣 接雨水 public class 接雨水 {public static int trap(int[] height){int res 0;int len height.length;int[] maxLeft new int[len];//存 i 左边最高的高度int[] maxRight new int[len];//存 i 右边最高的高度maxLeft[0] 0;maxRight[len - 1] 0; // DPfor (int i…