当前位置: 首页 > article >正文

el-table 组件二次封装(vue2)

PublicTable.vue

<!-- 公共表格组件 -->
<template>
  <div class="table-common">
    <el-table v-loading="loading" :ref="tableid" border style="width: 100%" :data="tableDatas" :row-key="rowKey"
      @selection-change="handleSelectionChange" @select="selectDataChange" @select-all="selectAllDataChange"
      :height="tableHeight" :header-cell-style="headerCellStyle" :row-style="rowStyle" highlight-selection-row
      :max-height="maxHeight" @row-click="handleRowClick" :tooltip-effect="configFlag.tooltip || 'dark'">
      <!-- 当数据为空时,如果想添加一个表达是空数据的图片,可以在这里设置,如果没有就不用管了 -->
      <template slot="empty">
        <el-empty class="empty_box" :image-size="55">
          <template slot="image">
            <img src="@/assets/icons/images/nodata.png">
          </template>
        </el-empty>
      </template>
      <!-- 全选单选 -->
      <el-table-column v-if="configFlag.selection" align="center" width="55" type="selection"
        :reserve-selection="configFlag.reserveSelection" />
      <!-- 序号列 -->
      <el-table-column type="index" v-if="configFlag.index" :label="configFlag.indexName || '序号'"
        :width="configFlag.indexWidth || 50" align="center" :fixed="configFlag.indexFixed || 'left'">
        <template slot-scope="scope">
          <!-- 每页都是从 1 开始 -->
          {{ scope.$index + 1 }}
          <!-- 第二页从 11 开始 -->
          <!-- {{ (pageValue.pageNum - 1) * 10 + (scope.$index + 1) }} -->
        </template>
      </el-table-column>

      <!-- 循环遍历表头展示数据 -->
      <el-table-column v-for="item in columnsCopy" :key="item.fieldIndex" :width="item.width || ''"
        :min-width="item.minWidth || ''" :prop="item.fieldIndex" :label="item.label" :align="item.align || 'center'"
        :sortable="item.sortable" :fixed="item.fixed || false" header-align="center"
        :show-overflow-tooltip="item.showOverFlowTooltip" :filters="item.filters ? item.filters : null"
        :filter-method="item.filters ? item.filtersMethod : null" :selectable="(row) => !row.isSelected">
        <template slot="header" slot-scope="{ column }">
          {{ column.label }}
          <el-tooltip class="item" effect="dark" v-if="item.headertip" :content="item.headertip" placement="top-start">
            <i class="el-icon-warning"></i>
          </el-tooltip>
        </template>
        <template slot-scope="scope">
          <!-- {{ scope }} -->
          <!-- 枚举值 -->
          <div v-if="item.type == 'statMap'">
            {{ statMaps(item.options)[scope.row[item.fieldIndex]] || "--" }}
          </div>
          <!-- 需提示过长信息 -->
          <div v-else-if="item.showOverFlowTooltip">
            <div class="show-tooltip">
              {{ scope.row[item.fieldIndex] || "--" }}
            </div>
          </div>
          <!-- 保留两位小数 -->
          <div v-else-if="item.type == 'tofix2'">
            {{
              scope.row[item.fieldIndex]
                ? Number(scope.row[item.fieldIndex]).toFixed(2)
                : "--"
            }}
          </div>
          <!-- 金额千分位展示,项目需求,所以暂时就加上了,主要是做个示例,大家可以参考怎么自定义列的一些方法 -->
          <div v-else-if="item.type == 'money'">
            <span>{{ getMoneyK(scope.row[item.fieldIndex]) || "--" }}</span>
          </div>
          <!-- 根据需求添加效果 返回的slot可以优化.自己来吧.可以实现操作列等 -->

          <slot v-else-if="item.type == undefined && item.slotname" :scope="scope" :field="item.fieldIndex"
            :name="item.slotname"></slot>
          <!-- 最普通的情况 -->
          <div v-else>
            <span>{{ scope.row[item.fieldIndex] || "--" }}</span>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination small v-if="configFlag.needPage" background :total="pageValue.total" :page-count="pageValue.pageNum"
      :page-size="pageValue.pageSize" :page-sizes="pageSizes" :current-page.sync="pageValue.pageNum"
      :layout="pageValue.pageLayout || pageLayout" class="_pagination" @size-change="sizeChange"
      @current-change="currentChange" @prev-click="prevClick" @next-click="nextClick" />
  </div>
</template>

<script>
export default {
  name: "Table",
  data() {
    return {
      tableDatas: [],
      loading: true,
      pageLayout: "total,prev, pager, next, jumper",
      columnsCopy: []
    };
  },
  props: {
    // 多选保存选中数据
    rowKey: {
      default: () => (row) => row.index,
    },
    // 为表头设计样式
    headerCellStyle: {
      default: () => {
        return { background: "rgb(243,248,254)" };
      },
    },
    // 为每一行设计样式,比如设置每行的高度等等
    rowStyle: {
      default: () => {
        return { height: "50px" };
      },
    },
    columns: {
      // 表头数据  文案和绑定值,以及需要特殊处理的slot
      type: Array,
      default: () => [],
    },
    tableData: {
      type: Array, // 后台数据
      default: () => [],
    },
    tableid: {
      type: String,
      default: "publicTable",
    },
    // 分页参数
    pageValue: {
      // 分页数据
      type: Object,
      default: () => {
        return {
          pageNum: 1,
          pageSize: 10,
          total: 0,
          currentPage: 1, //当前页
        };
      },
    },
    // 每页多少条的选项
    pageSizes: {
      type: Array,
      default: () => {
        return [10, 20, 50, 100];
      },
    },
    // 表格配置项
    configFlag: {
      // 配置  其他table配置依次添加
      type: Object,
      default: () => {
        return {
          needPage: false, // 是否需要分页
          selection: false, // 是否需要多选
          index: false, // 是否需要序号
          indexWidth: 70, //序号列宽
          btn: false, //序号添加自定义html
          reserveSelection: false,
          tooltip: 'dark'
          // 这里不全面,可根据实际情况添加
        };
      },
    },
    tableHeight: {
      // 可以监听屏幕高度获取。
      // 高度
      // type: Number || String ,
      default: () => null,
    },
    maxHeight: {
      // 可以监听屏幕高度获取。
      // 最大高度
      type: Number || String,
      default: () => 900,
    },
    // 是否可以点击行选中多选框
    rowClickSelect: {
      type: Boolean,
      default: true
    }
  },
  watch: {
    tableData: {
      handler: function (newvalue) {
        this.tableDatas = newvalue;
        this.loading = false;
      },
      deep: true,
    },
    columns: {
      handler: function (newvalue) {
        this.columnsCopy = newvalue;
      },
      deep: true,
    }
  },
  beforeUpdate() {
    this.tableDatas = this.$props.tableData;
    this.loading = false;
  },
  computed: {},
  mounted() {
    this.columnsCopy = this.$props.columns;
  },
  methods: {
    // 用于表格中字段是枚举值的列 比如性别 0 代表女 1代表男,就不需要对后台数据单独处理了
    handleRowClick(row) {
      if (this.rowClickSelect) {
        row.isSelected = !row.isSelected;
        this.$refs[this.tableid].toggleRowSelection(row);
      }
    },
    statMaps(list) {
      if (!list) return;
      let obj = {};
      list.forEach((item) => {
        obj[item.value || item.id] = item.label || item.value;
      });
      return obj;
    },
    // 金额千位展示:1,234,567,890
    getMoneyK(money) {
      if (typeof money === "number") {
        money = money.toString();
      }
      var pattern = /(-?\d+)(\d{3})/;
      while (pattern.test(money)) {
        money = money.replace(pattern, "$1,$2");
      }
      return money;
    },
    // 清空选中
    clearSelected() {
      // 父组件通过ref调用clearSelected方法,例如 this.$refs.clearTable.clearSelected()
      this.$refs[this.tableid]?.clearSelection();
    },
    /*
         默认选中
         需要默认选中的在组件中通过this.$refs[tableid].selected(默认选中的数据:Array)
        */
    selected(data) {
      if (data.length > 0) {
        data.forEach((item) => {
          this.$refs[this.tableid].toggleRowSelection(item, true);
        });
      }
    },
    // 设置条数
    sizeChange(size) {
      this.$emit("sizeChange", size);
    },
    // 翻页,直接跳转
    currentChange(page) {
      this.$emit("handleChange", page);
    },
    //上一页
    prevClick(val) {
      this.$emit("prevClick", val);
    },
    //下一页
    nextClick(val) {
      this.$emit("nextClick", val);
    },
    // 多选
    handleSelectionChange(val) {
      this.$emit("handleSelectionChange", val);
    },
    //点击选中取消选中
    selectDataChange(val, row) {
      this.$emit("selectDataChange", val, row);
    },
    selectAllDataChange(val) {
      this.$emit("selectAllDataChange", val);
    },
    // 多选
    handleSelection(val, row) {
      this.$emit("handleSelection", { val, row });
    },
    handleCellEnter(row, column, cell, event) {
      this.$emit("handleCellEnter", { row, column, cell, event });
    },
    //编辑
    handleEdit(index, row, colIndex, field) {
      this.$emit("handleEdit", { index, row, colIndex, field });
    },
    //下拉框事件
    onSelected(index, row, field) {
      this.$emit("onSelected", { index, row, field });
    },
    //按钮点击事件
    onClickBtn(index, row) {
      this.$emit("onClickBtn", { index, row });
    },
    filterHandler(value, row, column) {
      const property = column["property"];
      return row[property] === value;
    },
    /**重构表格布局 */
    handleResize() {
      this.$nextTick(() => {
        this.$refs[this.tableid].doLayout();
      });
    },
  },
};
</script>
<style lang="scss" scoped>
.show-tooltip {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  cursor: pointer;
}

/* 修改Tooltip样式 */
::v-deep .el-tooltip__popper.is-dark {
  background-color: #fff;
  /* 设置白色背景 */
  color: #000;
  /* 设置黑色字体 */
}

._pagination {
  width: 100%;
  margin: 5px 0;
  text-align: center;
}

.table-common {
  height: calc(100% - 30px);
}

::v-deep .empty_box {
  .el-empty__description {
    margin-top: 0;

    p {
      line-height: 50px;
    }
  }
}
</style>

用法:

<template>
    <div>
       <public-table ref="taskTable" :rowKey="(row) => row.id" :tableData="tableData" :columns="columns" :configFlag="tableConfig" @handleSelectionChange="selectChange" @sizeChange="handleSizeChange" @handleChange="handlePageChange" table-height="100%"></public-table>
    </div>
</template>
<script>
export default {
    data(){
        columns:[
          { label: '任务名称', fieldIndex: 'taskName', showOverFlowTooltip: true },
        ],
        tableConfig:{
            needPage: false, // 是否需要分页
            index: true, // 是否需要序号
            selection: true, // 是否需要多选
            reserveSelection: false, // 是否需要支持跨页选择
            indexFixed: 'left', // 序号列固定
        },
        tableData:[], // 表格数据
        pageValue: {
            // 分页参数
             total: 0,
             pageNum: 1,
             pageSize: 10,
             pageLayout: "total,sizes,prev,pager,next,jumper"
        },
        selectList:[], // 表格选中数据
    },
    methods:{
        // 表格多选事件
        selectChange(e){
            this.selectList = e;    
        },
        // 表格分页-页容改变
        handleSizeChange(e) {
            this.pageValue.pageSize = e;
            this.pageValue.pageNum = 1;
        },
        // 表格分页-页数改变
        handlePageChange(e) {
            this.pageValue.pageNum = e;
        }
    }
}
</script>


http://www.kler.cn/a/420622.html

相关文章:

  • JS实现高效导航——A*寻路算法+导航图简化法
  • yolov11剪枝
  • javaweb_Day05
  • Flask项目入门—request以及Response
  • mybatis-plus 对于属性为null字段不更新
  • 安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本
  • 【MATLAB源码-第230期】基于matlab的32QAM系统相位偏移估计HOS算法仿真,对比补偿前后的星座图误码率。
  • 机器学习算法(六)---逻辑回归
  • Qt Serial Bus 前置介绍篇
  • ​导游|基于SprinBoot+vue的在线预约导游系统
  • 【Django-xadmin】
  • Git命令大全(超详细)
  • 技术创新与人才培养并重 软通动力子公司鸿湖万联亮相OpenHarmony人才生态大会
  • 【Redis初阶】Zset 有序集合
  • 704. 二分查找 C++
  • C# winform非常好用的图表开源控件Scottplot
  • 基于SSM+vue的个性化商铺系统(源码+数据库+文档)
  • 【Elasticsearch】03-ES RESTFUL使用
  • TCP/IP 和 UDP
  • Flutter Container设置padding,margin,背景色,边框
  • AI开发-机器学习库-sklearn
  • jmeter学习(7)命令行控制
  • cocos creator 3.8 抖音、字节跳动录制器 12
  • 40 基于单片机的温湿度检测判断系统
  • 3D Bounce Ball Game 有什么技巧吗?
  • Linux笔记---进程:进程地址空间