vue+elementUI实现表格组件的封装

news2024/11/25 7:01:32

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

在父组件使用表格组件
<table-list
          ref="table"
          :stripe="true"
          :loading="loading"
          :set-table-h="slotProps.setMainCardBodyH"
          :table-data="tableData"
          :columns="columns.tableList || []"
          :radio="topicTypeListMapItem.radio"
          show-opear
          show-selection
          :fix-width="240"
          :page-data="pageData"
          :disabled-select-key="topicTypeListMapItem.disabledSelectKey"
          @changeSize="changeSize"
          @changePage="changePage"
        >
          <!--预警灯-->
          <template #warningLight="{ row }">
            <div class="lightCireBlock">
              <div>
                <div v-for="(item,index) in row.warningLight" :key="'warningLight'+index">
                  <svg-icon v-if="Object.keys(columns.warningLight).includes(item)" :icon-class="columns.warningLight[item].icon" class="task-icon" />
                  <span
                    v-if="columns.warningLight[item] && columns.warningLight[item].hasNum && row[`warningLight${item}`] * 1 > 0"
                    class="fontBoxAll fontBox"
                  >{{ row[`warningLight${item}`] }}</span>
                </div>
              </div>
            </div>
          </template>
          <!--标题-->
          <template #taskTitle="{ row }">
            <span class="td-cell lineCell" @click="editMainEvent(row)"> {{ row.taskTitle }}</span>
          </template>
          <!--状态-->
          <template #status="{ row }">
            <el-tag :disable-transitions="true" :class="columns.statusLists[row.status].className">{{ columns.statusLists[row.status].label }}</el-tag>
          </template>
          <!--操作-->
          <template slot-scope="{ row }">
            <div class="table-buttonList">
              <template v-for="(item,index) in columns.btnList">
                <el-button
                  v-if="item.isShow?item.isShow(row):true"
                  :key="index"
                  type="text"
                  @click="btnFn[item.clickFn.fn](row,...(item.clickFn.params?item.clickFn.params:[]))"
                >{{ item.name }}</el-button>
              </template>
            </div>
          </template>
        </table-list>

然后用一个js文件来存储动态的参数

import { selectOverseerMeetingLeaType } from '@/api/common.js'

export const topicTypeListMap = new Map([
  [
    'keyWork',
    {
      name: '重点工作',
      radio: false, // 表格数据是否单选
      showImportBtn: true, // 是否显示批量导入按钮
      showApprovalBtn: false, // 是否显示送立项按钮
      showImportApprovalBtn: false, // 导入时是否显示送立项按钮
      showItemTypeBtn: false, // 导入时是否显示选择事项类型按钮
      showWorkRequireBtn: false, // 导入时是否显示批量填写工作要求按钮
      showFoliCureBtn: false, // 是否显示送办理按钮
      hasSubtasks: true, // 专题是否有子任务
      isMeetingTopicType: false, // 是否是会议类专题
      disabledSelectKey: [{ label: 'status', value: '0' }, { label: 'status', value: '1' }] // 表格哪些状态的数据禁选
    }
  ],
  [
    'feasibleInstructions',
    {
      name: '督办件',
      radio: false,
      showImportBtn: true,
      showApprovalBtn: true,
      showImportApprovalBtn: true, // 导入时是否显示送立项按钮
      showItemTypeBtn: true, // 导入时是否显示选择事项类型按钮
      showWorkRequireBtn: false, // 导入时是否显示批量填写工作要求按钮
      showFoliCureBtn: true,
      hasSubtasks: false,
      isMeetingTopicType: false,
      disabledSelectKey: []
    }
  ]

])

在组件中

props传的参数

props: {
    // 表格数据
    tableData: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 表格字段
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 表格字段的宽度
    fixWidth: {
      type: Number,
      default: 150
    },
    // 单选
    radio: {
      type: Boolean,
      default: false
    },
    // 显示序号
    showIndex: {
      type: Boolean,
      default: false
    },
    // 是否自定义高度
    setTableH: {
      type: Boolean,
      default: true
    },
    // 显示勾选
    showSelection: {
      type: Boolean,
      default: false
    },
    // 显示操作
    showOpear: {
      type: Boolean,
      default: false
    },
    spanMethod: {
      type: Function,
      default() {
        return () => {}
      }
    },
    // 斑马线
    stripe: {
      type: Boolean,
      default: false
    },
    // 分页
    showPagination: {
      type: Boolean,
      default: true
    },
    setCheckbox: {
      type: Boolean,
      default: false
    },
    loading: { // 判断是否正在加载表格数据
      type: Boolean,
      default: false
    },
    align: {
      type: String,
      default: 'left'
    },
    recordCheck: { // 是否在翻页的时候记录之前选择的表格数据
      type: Boolean,
      default: true
    },
    // 分页数据
    pageData: {
      type: Object,
      default: () => {
        return {
          page: 1,
          rows: 15,
          pageSize: [15, 25, 35],
          total: 0
        }
      }
    },
    isImportData: { // 判断是否导入的数据
      type: Boolean,
      default: false
    },
    disabledSelectKey: { // 需要禁用的选择框的数据
      type: Array,
      default: () => {
        return []
      }
    }
  },

完整代码

<template>
  <div ref="wrap" class="wrap">
    <el-table
      ref="table"
      :key="'tableData'+tableData.length"
      v-loading="loading"
      element-loading-text="正在处理,请稍候!"
      :data="tableData"
      :stripe="stripe"
      :span-method="spanMethod"
      :header-row-class-name="headerRowClassName(radio)"
      :height="setTableH?setTableHeight:'100%'"
      class="table-list"
      border
      @sort-change="sortChange"
      @selection-change="handleSelectionChange"
    >
      <template slot="empty">
        <img src="@/assets/images/empty.png">
        <p>暂无数据</p>
      </template>

      <!--选择框-->
      <el-table-column v-if="showSelection" type="selection" width="42" :selectable="checkSelectable" />
      <!--序号-->
      <el-table-column v-if="showIndex" type="index" label="序号" width="55" align="center" />
      <el-table-column
        v-for="item in columns"
        :key="item.lable"
        :label="item.title"
        :prop="item.slot || item.lable"
        :min-width="item.minWidth || 140"
        :width="item.width"
        :sortable="item.sortable"
        :show-overflow-tooltip="item.overflow"
        :align="item.align"
      >
        <!-- 二级表头 -->
        <el-table-column
          v-for="subItem in item.columns"
          :key="subItem.label"
          :label="subItem.title"
          :prop="subItem.slot || subItem.lable"
          :min-width="subItem.minWidth || 140"
          :width="subItem.width"
          :sortable="subItem.sortable"
          :show-overflow-tooltip="subItem.overflow"
          :align="subItem.align"
        >
          <template slot="header">
            <!-- <span v-if="item.isRequest" style="color:red">*</span> -->
            <span> {{ subItem.title }}</span>
          </template>
          <template slot-scope="{ row }">
            <slot :name="subItem.slot" :row="row">
              <span class="td-cell"> {{ isImportData ? row[subItem.label].value : row[subItem.label] }}</span>
              <template v-if="isImportData">
                <el-popover
                  v-if="typeof(row[subItem.label].success) === 'boolean' && !row[subItem.label].success"
                  placement="top"
                  title=""
                  trigger="hover"
                  :content="row[subItem.label].message"
                >
                  <i slot="reference" class="el-icon-warning" style="color:#F44336" />
                </el-popover>
              </template>
            </slot>
          </template>
        </el-table-column>
        <template slot="header">
          <!-- <span v-if="item.isRequest" style="color:red">*</span> -->
          <span> {{ item.title }}</span>
        </template>
        <template slot-scope="{ row }">
          <slot :name="item.slot" :row="row">
            <span class="td-cell">{{ isImportData ? row[item.label].value : row[item.label] }}</span>
            <template v-if="isImportData">
              <el-popover
                v-if="typeof(row[item.label].success) === 'boolean' && !row[item.label].success"
                placement="top"
                title=""
                trigger="hover"
                :content="row[item.label].message"
              >
                <i slot="reference" class="el-icon-warning" style="color:#F44336" />
              </el-popover>
            </template>
          </slot>
        </template>
      </el-table-column>

      <!--操作按钮-->
      <el-table-column v-if="showOpear" label="操作" prop="operation" :width="fixWidth" fixed="right">
        <template #default="{ row, $index }">
          <slot :row="row" :$index="$index" />
        </template>
      </el-table-column>

    </el-table>
    <el-pagination
      v-if="showPagination && tableData.length>0"
      background
      :current-page="pageData.page"
      :page-size="pageData.rows"
      :page-sizes="pageData.pageSize"
      layout="sizes, prev, pager, next, slot, jumper"
      :total="pageData.total"
      class="pagination"
      @current-change="handleCurrentChange"
      @size-change="handleSizeChange"
    >
      <span class="pagination-total">{{ pageData.total }}条,</span>
    </el-pagination>
  </div>
</template>

<script>
import { clone } from 'lodash'
export default {
  name: 'TableList',
  props: {
    // 表格数据
    tableData: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 表格字段
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 表格字段的宽度
    fixWidth: {
      type: Number,
      default: 150
    },
    // 单选
    radio: {
      type: Boolean,
      default: false
    },
    // 显示序号
    showIndex: {
      type: Boolean,
      default: false
    },
    // 是否自定义高度
    setTableH: {
      type: Boolean,
      default: true
    },
    // 显示勾选
    showSelection: {
      type: Boolean,
      default: false
    },
    // 显示操作
    showOpear: {
      type: Boolean,
      default: false
    },
    spanMethod: {
      type: Function,
      default() {
        return () => {}
      }
    },
    // 斑马线
    stripe: {
      type: Boolean,
      default: false
    },
    // 分页
    showPagination: {
      type: Boolean,
      default: true
    },
    setCheckbox: {
      type: Boolean,
      default: false
    },
    loading: { // 判断是否正在加载表格数据
      type: Boolean,
      default: false
    },
    align: {
      type: String,
      default: 'left'
    },
    recordCheck: { // 是否在翻页的时候记录之前选择的表格数据
      type: Boolean,
      default: true
    },
    // 分页数据
    pageData: {
      type: Object,
      default: () => {
        return {
          page: 1,
          rows: 15,
          pageSize: [15, 25, 35],
          total: 0
        }
      }
    },
    isImportData: { // 判断是否导入的数据
      type: Boolean,
      default: false
    },
    disabledSelectKey: { // 需要禁用的选择框的数据
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data() {
    return {
      saveMultipleSelection: {}, // 用来保存每个分页勾选的数据
      multipleSelection: [],
      setTableHeight: 300
    }
  },
  computed: {
    headerRowClassName() {
      return (radio) => {
        if (radio) {
          return 'tableHead isRadio'
        } else {
          return 'tableHead'
        }
      }
    }
  },
  watch: {
    tableData: {
      handler(newVal) {
        this.$nextTick(() => {
          if (this.multipleSelection && this.recordCheck) {
            const idList = this.multipleSelection.map(item => { return item.businessKey })
            newVal.forEach(item => {
              if (idList.indexOf(item.businessKey) > -1) {
                this.$refs.table.toggleRowSelection(item, true)
              }
            })
          }
        })
      },
      deep: true
    },
    saveMultipleSelection: {
      handler(newVal) {
        this.multipleSelection = Object.keys(newVal).reduce((prev, next) => {
          prev = prev.concat(newVal[next])
          return [...new Set(prev)]
        }, [])
        this.$EventBus.$emit('selection-change', this.multipleSelection)
      },
      deep: true
    }
  },
  updated() {
    this.$nextTick(() => {
      this.setTableHeight = this.$refs.wrap.offsetHeight - document.querySelector('.el-table__header-wrapper').offsetHeight - 48 - 10
      // 10是给分页腾一点空间
    })
  },
  methods: {
    handleSizeChange(e) {
      this.$emit('changeSize', e)
    },
    handleCurrentChange(e) {
      this.$emit('changePage', e)
    },
    clearSort() {
      this.$refs.table.clearSort()
    },
    getSelection() {
      return clone(this.$refs.table.selection)
    },
    sortChange(e) {
      this.$emit('sortChange', e)
    },
    checkSelectable(row) {
      let check = true
      if (this.disabledSelectKey.length > 0) {
        this.disabledSelectKey.forEach(item => {
          if (row[item.label] === item.value) {
            check = false
          }
        })
      }
      return check
    },
    handleSelectionChange(val) {
      if (this.radio) { // 单选
        // var newRows = val.filter((it, index) => {
        //   if (index === val.length - 1) {
        //     this.$refs.table.toggleRowSelection(it, true)
        //     return true
        //   } else {
        //     this.$refs.table.toggleRowSelection(it, false)
        //     return false
        //   }
        // })
        // this.saveMultipleSelection = newRows
        this.$nextTick(() => {
          var newRows = val.filter((it, index) => {
            if (index === val.length - 1) {
              this.$refs.table.toggleRowSelection(it, true)
              return true
            } else {
              this.$refs.table.toggleRowSelection(it, false)
              return false
            }
          })
          if (val.length > 0) {
            this.saveMultipleSelection = {}
            this.$set(this.saveMultipleSelection, this.pageData.page, newRows)
          }
          // this.saveMultipleSelection = newRows
        })
      } else {
        this.$nextTick(() => {
          this.$set(this.saveMultipleSelection, this.pageData.page, val)
        })
      }
    },
    toggleRowSelection(row, bool) {
      this.$refs.table.toggleRowSelection(row, bool)
    }
  }

}
</script>
<style scoped lang="scss">
   .wrap{
     height: 100%;
      ::v-deep .isRadio {
        .el-checkbox{
          display: none;
        }
      }
   }
   ::v-deep .el-table ::-webkit-scrollbar{
      height: 8px;
    }
</style>

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

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

相关文章

JAVAEE——多线程进阶,锁策略

文章目录 锁策略乐观锁和悲观锁乐观锁悲观锁两者的比较 读写锁重量级锁和轻量级锁重量级锁轻量级锁 自旋锁公平锁和非公平锁公平锁非公平锁 可重入锁和不可重入锁可重入锁不可重入锁 锁策略 乐观锁和悲观锁 乐观锁 什么是乐观锁呢&#xff1f;我们可以认为乐观锁比较自信&am…

MySQL 连接池的实现

池化技术 池化技术能够减少资源对象的创建次数&#xff0c;提高程序的响应性能&#xff0c;特别是在高并发下这种提高更明显。共同特征 对象创建时间长。对象创建需要大量资源。对象创建后可被重复使用。 数据库连接池 数据库连接池&#xff08;Connection pooling&#xff…

linux C:变量、运算符

linux C 文章目录 变量运算符 一、变量 [存储类型] 数据类型 标识符 值 标识符&#xff1a;由数字、字母、下划线组成的序列&#xff0c;不能以数字开头。 数据类型&#xff1a;基本数据类型构造类型 存储类型&#xff1a;auto static…

2.4_2 死锁的处理策略——预防死锁

2.4_2 死锁的处理策略——预防死锁 知识总览 #mermaid-svg-z0noPuUcH4CJsxb7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-z0noPuUcH4CJsxb7 .error-icon{fill:#552222;}#mermaid-svg-z0noPuUcH4CJsxb7 .error-t…

【BlossomRPC】接入注册中心

文章目录 NacosZookeeper自研配置中心 RPC项目 配置中心项目 网关项目 这是BlossomRPC项目的最后一篇文章了&#xff0c;接入完毕注册中心&#xff0c;一个完整的RPC框架就设计完成了。 对于项目对注册中心的整合&#xff0c;其实我们只需要再服务启动的时候将ip/port/servic…

商城业务-检索服务

文章目录 前言一、搭建页面环境1.1 静态界面搭建1.2 Nginx 动静分离1.3 Windows 上传文件1.4 引入 thymeleaf 依赖1.5 Nginx 反向代理1.4 Nginx 配置1.5 gateway 网关配置 二、调整页面跳转2.1 引入依赖2.2 页面跳转 三、检索查询参数模型分析抽取3.1 检索业务分析3.2 检索语句…

齿轮“红宝书”

​在齿轮行业&#xff0c;有两本书被广大从业者尊称为“红宝书”。这两部作品深入剖析了齿轮技术的精髓&#xff0c;为从业者提供了宝贵的指导和启示。它们犹如行业的明灯&#xff0c;照亮了齿轮制造的每一个角落&#xff0c;使得从业者在探索中不再迷茫。 这两本红宝书的内容…

遥感动态监测技术

很多人对动态监测和动态检测两个名词有疑惑。我们可以这样理解&#xff0c;动态监测是一个广义的名词&#xff0c;泛指数据预处理、变化信息发现与提取、变化信息挖掘与应用等&#xff0c;以对整个流程的叙述。动态检测是一个狭义的名词&#xff0c;主要指部分数据预处理、变化…

【御控物联】JavaScript JSON结构转换(7):数组To数组——键值互换属性重组

文章目录 一、JSON结构转换是什么&#xff1f;二、案例之《JSON数组 To JSON数组》三、代码实现四、在线转换工具五、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0c;生成新的JS…

前端(三)React踩坑记录

一、引言 作者最近新的平台项目是需要用react的&#xff0c;和vue区别还是比较大的&#xff0c;这里记录下踩坑和使用经验。 二、环境 框架&#xff1a;antd 依赖&#xff1a; "dependencies": {"ant-design/icons": "^4.7.0","ant-desig…

Linux使用Docker部署RStudio Server结合内网穿透实现公网访问本地服务

文章目录 前言1. 安装RStudio Server2. 本地访问3. Linux 安装cpolar4. 配置RStudio server公网访问地址5. 公网远程访问RStudio6. 固定RStudio公网地址 前言 RStudio Server 使你能够在 Linux 服务器上运行你所熟悉和喜爱的 RStudio IDE&#xff0c;并通过 Web 浏览器进行访问…

卷积层+多个输入通道

卷积层多输入输出通道 在深度学习中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;通常用于处理具有多个输入通道的数据。当输入数据具有多个通道&#xff08;例如彩色图像的RGB通道&#xff09;时&#xff0c;卷积操作可以同时在每个通道上进行&#xff0c;并将各通道的…

【成功案例】间隔数月双团伙先后利用某ERP0day实施入侵和勒索的解密恢复项目

1.背景 在2024年3月23日&#xff0c;我们的Solar应急响应团队&#xff08;以下简称Solar团队&#xff09;应某公司之邀&#xff0c;介入处理了一起财务系统服务器遭受黑客攻击的事件。该事件导致服务器上大量文件被加密。我们的团队迅速获取了一个被加密的文件&#xff0c;并立…

面试题:MySQL 优化篇

定位慢查询 &#x1f496; 开源工具 调试工具&#xff1a;Arthas&#xff08;阿尔萨斯&#xff09;运维工具&#xff1a;Prometheus&#xff08;普罗米修斯&#xff09;、Skywalking &#x1f496; MySQL 慢查询日志 # 开启 MySQL 慢查询日志开关 slow_query_log1 # 设置慢…

HWOD:整型数组排序

一、知识点 while(1){}表示永久循环 使用break结束循环 二、题目 1、描述 输入整型数组和排序标识&#xff0c;对其元素按照升序或降序进行排序 2、数据范围 1<n<1000 0<val<100000 3、输入 第一行输入数组元素个数 第二行输入待排序的数组&#x…

安装JupyterLab的集成环境

Python集成环境安装 不要半途而废&#xff0c;不要作业太多就抛下你手中的笔&#xff0c;拿起你旁边的手机&#xff0c;你觉得这样很有意义吗&#xff1f;一个小时一道题都没做&#xff0c;盯着手机屏幕它能给你一个未来吗&#xff1f;少分心就能多做一道题&#xff0c;多学样本…

编程新手必看,Python开发环境工具揭秘:高效编程的必备工具(2)

1、Python主流的开发工具介绍&#xff1a; Python的主流开发工具主要包括PyCharm、Visual Studio Code&#xff08;VS Code&#xff09;、IDLE等。具体介绍如下&#xff1a; 1.1、PyCharm&#xff1a; PyCharm是由JetBrains开发的&#xff0c;专为Python设计的IDE&#xff0…

生成 SSH 公钥

Windows 用户建议使用 Windows PowerShell 或者 Git Bash&#xff0c;在 命令提示符 下无 cat 和 ls 命令。 1、通过命令 ssh-keygen 生成 SSH Key&#xff1a; ssh-keygen -t ed25519 -C "Gitee SSH Key"-t key 类型 -C 注释 输出&#xff0c;如&#xff1a; 中间…

【tensorflow框架神经网络实现鸢尾花分类_Keras】

文章目录 1、前言2、鸢尾花分类3、结果打印 1、前言 【tensorflow框架神经网络实现鸢尾花分类】一文中使用自定义的方式&#xff0c;实现了鸢尾花数据集的分类工作。在这里使用tensorflow中的keras模块快速、极简实现鸢尾花分类任务。 2、鸢尾花分类 import tensorflow as t…