elementUI table组件封装(vue)

前段时间公司做了一个新项目,后台管理这种,大部分都是表格,UI框架用的是element,所以我刚好把表格组件封装了一下,

elementUI表格组件常用的功能就是单选/多选框勾选,数据展示,行内按钮操作等,这块我也是基于本当前项目的需求大概封装的,比elementUI多的就是一个动态显示隐藏列的功能,这里记录一下

<template>
  <div class="tabletemplate">
    <!-- 动态显示隐藏列功能 -->
    <el-dropdown
      v-if="selectColumns" // 动态列功能是否显示
      :hide-on-click="false"
      @visible-change="dropdownSelectShow"
      class="el-dropdown-selectColumn"
      trigger="click"
    >
      <span class="dropdown-button" :style="theme.sysTheme.styleLevel4">
        <i
          class="icon iconfont iconcaidan1"
          :style="theme.sysTheme.colorLevel3"
        ></i>
      </span>
      <el-dropdown-menu slot="dropdown" style="text-align: center;">
        <!-- <CheckboxGroup v-model="tableColumnsCheckedShow" @on-change="changeTableColumns"> -->
        <div class="dropdowntable" style="text-align: left;">
          <el-dropdown-item v-for="(item, index) in tableColumns" :key="index">
            <!-- <Checkbox :label="item.title">{{item.title}}</Checkbox> -->
            <template>
              <el-checkbox
                :checked="item.isShow"
                v-model="item.isShow"
                @change="checkChange(item)"
                >{{ item.title }}</el-checkbox
              >
            </template>
          </el-dropdown-item>
        </div>
        <!-- <el-button
          type="primary"
          style="margin: auto;padding: 5px 15px;"
          @click="buttonclick(tableColumns)"
        >确定</el-button> -->
        <!-- </CheckboxGroup> -->
      </el-dropdown-menu>
    </el-dropdown>

    <el-table
      :data="tableData"
      stripe
      border
      v-loading="loading"
      highlight-current-row
      :header-cell-style="{
        'background-color': headerBackColor,
        color: '#333'
      }"
      :cell-style="{
        'background-color': '#ffffff',
        'border-color': cellBorderColor
      }"
      :row-style="{ border: 'none' }"
      show-overflow-tooltip
      style="width: 100%;margin-top: 0.24rem;"
      @selection-change="handleSelectionChange"
      ref="multipleTable"
    >
      <!--选择-->
      <el-table-column
        v-if="selectionShow" // 表格是够显示多选框
        type="selection"
        align="center"
        :width="selectionWith"
      ></el-table-column>
      // 单选框,多选单选只能选则显示一个或者都不显示
      <el-table-column v-if="radioShow && !selectionShow" :width="radioWidth">
        <template slot-scope="scope">
          <el-radio
            v-model="radioVal"
            @change.native="getRow(scope.row)"
          ></el-radio>
        </template>
      </el-table-column>
      <!--序号 自定义列序号-->
      <el-table-column
        v-if="indexShow"
        type="index"
        align="center"
        label="序号"
        fixed="left"
        :width="indexWidth"
      >
        <template slot-scope="scope">
          <span>{{ (page - 1) * size + scope.$index + 1 }}</span>
        </template>
      </el-table-column>
      <!-- :width="column.width ? column.width: ''" -->
      <!-- 表格数据列 -->
      <el-table-column
        align="center"
        v-for="column in tableColumns"
        v-if="selectColumns ? column.isShow || !isshowShow : true"
        :key="column.key"
        :label="column.title"
        show-overflow-tooltip
      >
        <template slot-scope="scope">
          <span
            v-if="scope.row.activeStatus === '在线'"
            style="color:#13CE66"
            >{{ scope.row.activeStatus }}</span
          >
          <!-- <span v-else-if="scope.row.accessCode">
            <span v-if="scope.row.accessCode === '3'"
              >高于{{ scope.row.additionalRule }}分钟不得分</span
            >
            <span v-else-if="scope.row.accessCode === '4'">无</span>
            <span v-else>低于{{ scope.row.additionalRule }}%不得分</span>
          </span> -->
          <span v-else>{{ scope.row[column.key] }}</span>
        </template>
      </el-table-column>
      <!--操作-->
      <el-table-column
        v-if="tableOperationShow" // 操作按钮是否显示
        :width="operationColumnWidth"
        label="操作"
        align="center"
        fixed="right"
      >
        <!-- 操作列按钮的个数,名称,功能都是可以自定义的 -->
        <template slot-scope="scope">
          <!-- <div class="tablecloumnview"> -->
          <span
            class="font-small font-color-light operationSpan"
            v-if="viewDetail"
            @click="tableOperationBtn1Handle(scope.row)"
            >{{ tableOperationText1 }}</span
          >
          <span
            class="font-small font-color-light operationSpan"
            v-if="linkLogin"
            @click="tableOperationBtn2Handle(scope.row)"
            >{{ tableOperationText2 }}</span
          >
          <span
            class="font-small font-color-light operationSpan"
            v-if="linkLogout"
            @click="tableOperationBtn3Handle(scope.row)"
            >{{ tableOperationText3 }}</span
          >
          <!-- </div> -->
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

该组件可以动态设置是否显示动态列功能,那么什么是动态列功能呢,其实就是一个按钮,点击会出现一个下拉框,里面是表格所有列名组成的列表,每一个列名可以根据需求显示,勾选则显示,取消勾选则隐藏。实现原理是v-if控制当前列的显示,表格列数据中有一个参数用来控制当前列的显示与隐藏。

<script>
import { mapGetters } from "vuex";
import createUpDeleteGive from "@/components/buttons/createUpDelGive"; // 按钮组件,很简单不做介绍
export default {
  name: "tabletemplate",
  components: {
    createUpDeleteGive
  },
  props: {
    headerBackColor: { // 表头背景颜色
      type: String,
      default: "#F5F5F5"
    },
    cellBackColor: { // 表格单元格背景颜色
      type: String,
      default: "#FFFFFF"
    },
    cellBorderColor: { // 表格单元格边框颜色
      type: String,
      default: "#E6E6E6"
    },
    selectColumns: { // 是否显示动态列功能,默认显示
      // 动态列功能
      type: Boolean,
      default: true
    },
    tableData: { // 表格数据
      type: Array,
      required: true,
      default: function() {
        return [];
      }
    },
    tableColumns: { // 表格列数据
      type: Array,
      required: true,
      default: function() {
        return [];
      }
    },
    isshowShow: {
      // 是否控制列的动态显示 默认控制
      type: Boolean,
      default: true
    },
    page: {
      type: Number,
      default: 1
    },
    size: {
      type: Number,
      default: 10
    },
    selectionWith: {
      type: Number,
      required: false,
      default: 50
    },
    radioWidth: {
      type: Number,
      required: false,
      default: 40
    },
    operationColumnWidth: {
      // 表格操作列宽度
      type: Number,
      required: false,
      default: 100
    },
    indexWidth: {
      type: Number,
      required: false,
      default: 55
    },
    selectionShow: {
      // 多选   默认显示多选
      type: Boolean,
      default: true
    },
    radioShow: {
      // 单选 使用单选应将多选置为false
      type: Boolean,
      default: false
    },
    indexShow: {
      // 序号列
      type: Boolean,
      default: true
    },
    tableOperationShow: {
      // 最后操作列
      type: Boolean,
      required: false,
      default: false
    },
    linkLogin: {
      type: Boolean,
      required: false,
      default: false
    },
    linkLogout: {
      type: Boolean,
      required: false,
      default: false
    },
    viewDetail: {
      type: Boolean,
      default: true
    },
    loading: {
      type: Boolean,
      default: false
    },
    tableOperationText1: {
      type: String,
      default: "查看详情"
    },
    tableOperationText2: {
      type: String,
      default: "链路登录"
    },
    tableOperationText3: {
      type: String,
      default: "链路注销"
    }
  },
  data() {
    return {
      tableColumnsCheckedShow: [],
      radioVal: -1
    };
  },
  methods: {
    handleSelectionChange(val) {
      // console.log(val);
      this.$emit("handleSelectionChange", val);
    },
    tableOperationBtn1Handle(row) {
      this.$emit("tableOperationBtn1Handle", row);
    },
    tableOperationBtn2Handle(row) {
      this.$emit("tableOperationBtn2Handle", row);
    },
    tableOperationBtn3Handle(row) {
      this.$emit("tableOperationBtn3Handle", row);
    },
    checkChange(val) {
      console.log("checkChange");
      // console.log(val);
    },
    getRow(row) {
      // console.log(row);
      this.$emit("giveTableRowData", row);
    },
    buttonclick(row) {},
    reset() {
      this.radioVal = -1;
      this.$refs["multipleTable"].clearSelection();
    },
    dropdownSelectShow(val) {
      if (val === true) {
        // var mo = function(e) {
        //   e.preventDefault();
        // };
        // document.body.style.overflow = "hidden";
        // document.addEventListener("touchmove", mo, false); //禁止页面滑动
        var scorllbar = document.querySelector(".form-table-content");
        scorllbar.addEventListener(
          "scorll",
          function(e) {
            e.preventDefault();
            e.stopPropagation();
            console.log("页面滚动事件");
            scorllbar.scrollTop = 0;
          },
          { passive: false }
        );
      }
    }
  },
  mounted() {},
  computed: {
    ...mapGetters(["currentNav", "theme"])
  }
};
</script>
<style lang="scss" scoped>
.tabletemplate {
  .el-dropdown-selectColumn {
    position: relative;
    float: right;
    .dropdown-button {
      cursor: pointer;
      position: absolute;
      z-index: 1000;
      top: 0px;
      left: -16px;
    }
    .dropdowntable {
      width: 100%;
      max-height: 200px !important;
      overflow: auto !important;
    }
  }
  .selectColumn {
    margin-bottom: 10px;
    height: auto;
  }
  .operationSpan {
    display: inline-block;
    width: 0.7rem;
    margin: 0 0.05rem;
    min-width: 40px;
    text-align: center;
    white-space: nowrap;
    cursor: pointer;
    font-size: 12px;
    font-family: "MicrosoftYaHei";
    font-weight: 400;
  }
}
</style>

封装就到这里了,那怎么调用呢?

        <table-template
          :tableData="tableList" // 表格数据
          :tableColumns="listColumns" // 表头列数据
          :loading="loading"
          :selectionShow="false"
          :selectColumns="false"
          :headerBackColor="headerBackColor"
          :cellBackColor="cellBackColor"
          :cellBorderColor="cellBorderColor"
        ></table-template>

表格数据当然是后台获取,但是表头列数据可以后台获取,也可以前台定义,可以是这种格式:

tableColumns: [
        {
          key: "company",
          title: "企业",
          width: "150",
          isShow: true // 控制当前列是否显示
        },
        {
          key: "networkAccessRate",
          title: "入网率",
          width: "150",
          isShow: true
        },
        {
          key: "networkAccessScore",
          title: "入网率得分",
          width: "150",
          isShow: true
        },
        {
          key: "onlineRate",
          title: "上线率",
          width: "150",
          isShow: true
        },
        {
          key: "onlineScore",
          title: "上线率得分",
          width: "150",
          isShow: true
        },
        {
          key: "trackIntegrityRate",
          title: "轨迹完整率",
          width: "150",
          isShow: true
        }
      ]

 

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
ElementUItable 组件提供了非常丰富的功能和接口,但是在实际项目中,我们经常需要对其进行二次封装,以满足自己的业务需求。下面是一个简单的 ElementUI table 的二次封装示例: ```vue <template> <el-table :data="tableData" :height="height" :max-height="maxHeight" :stripe="stripe" :border="border" :fit="fit" :show-header="showHeader" :highlight-current-row="highlightCurrentRow" :row-class-name="rowClassName" :row-style="rowStyle" :cell-class-name="cellClassName" :cell-style="cellStyle" :header-row-class-name="headerRowClassName" :header-row-style="headerRowStyle" :header-cell-class-name="headerCellClassName" :header-cell-style="headerCellStyle" :row-key="rowKey" @select="handleSelect" @select-all="handleSelectAll" @selection-change="handleSelectionChange" @cell-mouse-enter="handleCellMouseEnter" @cell-mouse-leave="handleCellMouseLeave" @cell-click="handleCellClick" @cell-dblclick="handleCellDblClick" @row-click="handleRowClick" @row-contextmenu="handleRowContextMenu" @row-dblclick="handleRowDblClick" @header-click="handleHeaderClick" @header-contextmenu="handleHeaderContextMenu" @sort-change="handleSortChange" @filter-change="handleFilterChange" > <slot></slot> </el-table> </template> <script> export default { name: "MyTable", props: { tableData: { type: Array, default: () => [] }, height: { type: [Number, String], default: "" }, maxHeight: { type: [Number, String], default: "" }, stripe: { type: Boolean, default: true }, border: { type: Boolean, default: true }, fit: { type: Boolean, default: true }, showHeader: { type: Boolean, default: true }, highlightCurrentRow: { type: Boolean, default: true }, rowClassName: { type: Function, default: () => undefined }, rowStyle: { type: Function, default: () => undefined }, cellClassName: { type: Function, default: () => undefined }, cellStyle: { type: Function, default: () => undefined }, headerRowClassName: { type: Function, default: () => undefined }, headerRowStyle: { type: Function, default: () => undefined }, headerCellClassName: { type: Function, default: () => undefined }, headerCellStyle: { type: Function, default: () => undefined }, rowKey: { type: [String, Function], default: "" } }, methods: { handleSelect(selection, row) { this.$emit("select", selection, row); }, handleSelectAll(selection) { this.$emit("select-all", selection); }, handleSelectionChange(selection) { this.$emit("selection-change", selection); }, handleCellMouseEnter(row, column, cell, event) { this.$emit("cell-mouse-enter", row, column, cell, event); }, handleCellMouseLeave(row, column, cell, event) { this.$emit("cell-mouse-leave", row, column, cell, event); }, handleCellClick(row, column, cell, event) { this.$emit("cell-click", row, column, cell, event); }, handleCellDblClick(row, column, cell, event) { this.$emit("cell-dblclick", row, column, cell, event); }, handleRowClick(row, event, column) { this.$emit("row-click", row, event, column); }, handleRowContextMenu(row, event) { this.$emit("row-contextmenu", row, event); }, handleRowDblClick(row, event) { this.$emit("row-dblclick", row, event); }, handleHeaderClick(column, event) { this.$emit("header-click", column, event); }, handleHeaderContextMenu(column, event) { this.$emit("header-contextmenu", column, event); }, handleSortChange({ column, prop, order }) { this.$emit("sort-change", { column, prop, order }); }, handleFilterChange(filters) { this.$emit("filter-change", filters); } } }; </script> ``` 这里我们定义了一个名为 `MyTable` 的组件,并将其 props 与 ElementUI table 组件的 props 一一对应。在组件的模板中,我们使用了 `<slot></slot>`,表示组件的插槽,这样可以让用户在使用组件时自定义表格和内容。在组件的方法中,我们将 ElementUI table 的事件通过 `$emit` 的方式向上传递,这样可以使得组件的使用更加灵活。 使用这个组件时,我们只需要在父组件中引入 `MyTable` 组件,并将需要的 props 和插槽传入即可: ```vue <template> <my-table :table-data="tableData" :stripe="false" :highlight-current-row="false" @row-click="handleRowClick" > <el-table-column label="姓名" prop="name"></el-table-column> <el-table-column label="年龄" prop="age"></el-table-column> <el-table-column label="地址" prop="address"></el-table-column> </my-table> </template> <script> import MyTable from "@/components/MyTable"; export default { name: "MyPage", components: { MyTable }, data() { return { tableData: [ { name: "张三", age: 18, address: "北京市" }, { name: "李四", age: 20, address: "上海市" }, { name: "王五", age: 22, address: "广州市" } ] }; }, methods: { handleRowClick(row) { console.log(row); } } }; </script> ``` 这样,我们就完成了一个简单的 ElementUI table 的二次封装,并且可以在父组件中灵活使用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值