当前位置: 首页 > 工具软件 > UI Table Edit > 使用案例 >

element ui el-table进行二次封装

陆晓博
2023-12-01

ement ui Table 二次封装

在做项目的时候特别是后台管理的时候table难免用的多,所有根据vue框架对table进行二次封装
好处那就是可以省很多代码,而且用起来也方便。非常的奈斯


  • 封装的内容
  <div class="hs-table">
    <el-table
      :class="comFooterShow ? 'singleTable' : 'notFooterTable'"
      ref="singleTable"
      :highlight-current-row="selectCurRow"
      @current-change="handleCurChange"
      :data="dataProcessing()"
      stripe
      :max-height="maxHeight"
      :show-header="showHeader"
      :size="size"
      :row-key="getKey"
      @selection-change="selectionChange"
    >
      <!-- 自定义表格首列显示内容 -->
      <slot name="firstCustom"></slot>
      <el-table-column
        v-if="selectionShow"
        align="center"
        type="selection"
        width="45"
        :reserve-selection="true"
      >
      </el-table-column>
      <el-table-column v-if="expandShow" type="expand" width="30">
        <template slot-scope="props">
          <div class="flex-jc-flex-end">
            <div class="work-order-spli">
              <slot name="expand" :props="props"></slot>
            </div>
          </div>
        </template>
      </el-table-column>
      <template v-for="(item, index) in tableHead">
        <el-table-column
          v-if="item.time"
          :label="item.column_comment"
          :key="index + item.column_comment"
          :show-overflow-tooltip="item.showTooltip ? item.showTooltip : false"
          :width="item.width"
          :sortable="item.sortable"
          :sort-method="(a, b) => sortTimeFun(a, b, item.column_name)"
          :prop="item.column_name"
        >
          <template slot-scope="scope">
            <div>{{ setTime(scope.row, item.column_name) }}</div>
          </template>
        </el-table-column>
        <template v-else-if="item.custom">
          <slot name="custom" :index="index" :item="item"></slot>
        </template>
        <el-table-column
          v-else
          :prop="item.column_name"
          :label="item.column_comment"
          :key="index + item.column_name"
          :show-overflow-tooltip="item.showTooltip ? item.showTooltip : false"
          :width="item.width"
          :sortable="item.sortable"
        ></el-table-column>
      </template>
      <template v-if="defaultBtn">
        <el-table-column width="80" align="center" label="操作">
          <template slot-scope="scope">
            <el-popover
              v-model="scope.row.popoverShow"
              placement="bottom"
              trigger="click"
            >
              <div style="padding: 8px">
                <el-button
                  v-if="editShow"
                  size="mini"
                  icon="el-icon-edit"
                  type="primary"
                  :disabled="disabled"
                  @click="handleEdit(scope.$index, scope.row)"
                  >编辑</el-button
                >
                <el-button
                  v-if="deleteShow"
                  size="mini"
                  type="danger"
                  @click="handleDelete(scope.$index, scope.row)"
                  icon="el-icon-delete"
                  :disabled="disabled"
                  >删除</el-button
                >
                <slot name="otherBtn" :scope="scope"></slot>
              </div>
              <el-button
                class="button-no-border"
                size="mini"
                icon="el-icon-more"
                slot="reference"
              ></el-button>
            </el-popover>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <div
      v-if="comFooterShow"
      class="flex-jc-space-between-d"
      style="margin: 20px 0px 0px"
    >
      <div class="flex-jc-flex-start">
        <template v-if="allSelectShow">
          <el-checkbox
            :disabled="!dataProcessing().length"
            :indeterminate="isCheckbox"
            @change="toggleAllSelect"
            size="small"
            v-model="selectAll"
            >全选</el-checkbox
          >
          <slot name="batchOperation" :selectData="selectData"></slot>
        </template>
      </div>
      <div
        class="paginationBox"
        v-if="paginationShow"
        style="text-align: right"
      >
        <el-pagination
          class="pagination"
          background
          layout="total, sizes, prev, pager, next"
          :hide-on-single-page="tableSetting.paginationDis"
          :small="tableSetting.smallPage"
          :pager-count="tableSetting.pagerCount"
          :total="totalData"
          :current-page="tableSetting.currentPage"
          @current-change="handelCurChange"
          @prev-click="handelCurChange"
          @next-click="handelCurChange"
          :page-size="tableSetting.pageSize"
          :page-sizes="[1, 20, 50, 100, 500]"
          @size-change="handleSizeChange"
        ></el-pagination>
      </div>
    </div>
  </div>
  • 组件内的按钮以及复选框分页都是通过变量来控制。
  props: {
    disabled: {
      type: Boolean,
      default: false,
    },
    showHeader: {
      type: Boolean,
      default: true,
    },
    selectionShow: {
      // 多选框
      type: Boolean,
      default: false,
    },
    expandShow: {
      // 表格可展开 false默认不可以  true可以
      type: Boolean,
      default: false,
    },
    defaultBtn: {
      // 显示操作列(默认按钮),如果设置false则不显示
      type: Boolean,
      default: true,
    },
    allSelectShow: {
      // 显示全选按钮,默认不显示
      type: Boolean,
      default: false,
    },
    paginationShow: {
      // 显示默认按钮,如果设置false则可以自定义
      type: Boolean,
      default: true,
    },
    editShow: {
      // 编辑按钮显示
      type: Boolean,
      default: true,
    },
    deleteShow: {
      // 删除按钮显示
      type: Boolean,
      default: true,
    },
    selectCurRow: {
      // 当前可选择
      type: Boolean,
      default: true,
    },
    maxHeight: {
      // 固定高度
      type: [Number, String],
      default: "100vh",
    },
    fontSize: {
      // 表格字体大小
      type: String,
      default: "24px",
    },
    size: {
      // 表格大小控制
      type: String,
      default: null,
    },
    tableHead: {
      // 表头数据
      type: Array,
      default: function () {
        return [];
      },
    },
    tableData: {
      // 表格数据
      type: Array,
      default: function () {
        return [];
      },
    },
    pageFlag: {
      // 后端分页(或显示全部都显示为true) 开启后必须使用total字段  false=>前端分页
      type: Boolean,
      default: false,
    },
    total: {
      // 数据总数  pageFlag:true 才生效
      type: Number,
      default: 0,
    },
  },

 data() {
    return {
      tableSetting: {
        total: 0, // 总数
        currentPage: 1, // 当前页
        pageSize: 20, // 每页显示数量
        paginationDis: false, // 1个分页则隐藏分页标签
        smallPage: false, // 小型分页样式
        pagerCount: 5, //页码按钮的数量,当总页数超过该值时会折叠
      },
      selectAll: false,
      isCheckbox: false,
      selectData: [],
    };
  },
  • 组件内部也是写了方法通过子传父使父组件更好的去使用。
  computed: {
    comFooterShow() {
      return this.allSelectShow || this.paginationShow;
    },
    totalData() {
      if (this.pageFlag) {
        return this.total;
      } else {
        return this.tableData.length;
      }
    },
  },
  methods: {
    initTableSetting() {
      let that = this;
      that.tableSetting = {
        total: 0, // 总数
        currentPage: 1, // 当前页
        pageSize: 20, // 每页显示数量
        paginationDis: false, // 1个分页则隐藏分页标签
        smallPage: false, // 小型分页样式
        pagerCount: 5, //页码按钮的数量,当总页数超过该值时会折叠
      };
    },
    handelCurChange(page) {
      // 改变当前页
      console.log("改变当前页", page);
      let that = this;
      that.tableSetting.currentPage = page;
      that.$emit("change-page", that.tableSetting);
    },
    handleSizeChange(val) {
      // 选择显示数据量
      console.log(`每页 ${val} 条`);
      console.log(val);
      let that = this;
      that.tableSetting.pageSize = val;
      that.tableSetting.currentPage = 1;
      that.$emit("change-page", that.tableSetting);
    },
    toggleAllSelect(val) {
      let that = this;
      console.log("toggleAllSelect", val);
      if (val) {
        that.$refs.singleTable.toggleAllSelection();
      } else {
        that.$refs.singleTable.clearSelection();
      }
      that.isCheckbox = false;
    },
    selectionChange(val) {
      console.log("selectionChange", val);
      let that = this;
      that.selectData = val;
      let checkedCount = val && val.length ? val.length : 0;
      that.selectAll = checkedCount === that.tableData.length;
      that.isCheckbox =
        checkedCount > 0 && checkedCount < that.tableData.length;
      that.$emit("select-data", that.selectData);
    },
    handleCurChange(val) {
      // 选择当前行
      let that = this;
      // console.log("选择当前行", val);
      that.$emit("select-current", val);
    },
    setCurrent(row) {
      let that = this;
      // 选择表格第几行
      that.$refs.singleTable.setCurrentRow(row);
      console.log("选择表格第几行", row);
    },
    handleDelete(index, val) {
      // 删除按钮事件
      let that = this;
      console.log("删除", val);
      val.popoverShow = false;
      that.$emit("handle-delete", val);
    },
    handleEdit(index, val) {
      // 编辑按钮事件
      // console.log("编辑", val);
      let that = this;
      val.popoverShow = false;
      that.$emit("handle-edit", val);
    },
    getKey(row) {
      return row.Id;
    },
    dataProcessing() {
      // 分页功能
      let that = this;
      let data = [];
      if (that.pageFlag) {
        data = that.tableData;
      } else {
        let pageSize = that.tableSetting.pageSize;
        let currentPage = that.tableSetting.currentPage;
        data = that.tableData.slice(
          (currentPage - 1) * pageSize,
          currentPage * pageSize
        );
      }

      return data;
    },
    sortTimeFun(a, b, columnName) {
      let nameArr = columnName.split("."); // 通过.截取处理每一层的key
      let dataA = JSON.parse(JSON.stringify(a));
      let dataB = JSON.parse(JSON.stringify(b));
      nameArr.forEach((item) => {
        // 遍历拿到最后的值
        dataA = dataA[item];
        dataB = dataB[item];
      });
      return Date.parse(dataA) - Date.parse(dataB);
    },
    setTime(val, name) {
      let nameArr = name.split(".");
      // console.log(val, nameArr);
      let data = val;
      nameArr.forEach((item) => {
        data = data[item];
      });
      // console.log(data);
      if (data) {
        return SysGlobal.formatDateTime(data);
      }
    },
  },
  • 组件样式
<style scoped lang="scss">
.hs-table::v-deep {
  height: 100%;
  .paginationBox {
    height: 32px;
  }
  .el-table.singleTable {
    height: calc(100% - 53px);
    display: flex;
    flex-direction: column;
    .el-table__header-wrapper {
      flex: none;
    }
    .el-table__body-wrapper {
      flex: auto;
      overflow: auto;
    }
    .cell {
      height: 100%;
      line-height: normal;
    }
  }
  .el-table.notFooterTable {
    height: 100%;
    display: flex;
    flex-direction: column;
    .el-table__header-wrapper {
      flex: none;
    }
    .el-table__body-wrapper {
      flex: auto;
      overflow: auto;
    }
    .cell {
      height: 100%;
      line-height: normal;
    }
  }
}
.work-order-spli {
  width: calc(100% - 95px);
}
.color-box-flex {
  display: flex;
  justify-content: flex-start;
}
.doc-lock {
  padding: 4px 4px;
  font-size: 18px;
  border-radius: 4px;
  cursor: pointer;
}
.doc-lock:hover {
  background-color: white;
}
</style>
  • 在需要的页面使用
    值得一提的是,父组件可以通过插槽来进行对某些字段特殊处理
    还可以根据页面需求在操作的一列中加入权限分配了。。。。。。
 <el-card>
      <Table
        :default-btn="true"
        :edit-show="true"
        :pageFlag="true"
        :selectionShow="true"
        :table-head="tableData.header"
        :table-data="tableData.list"
        :total="tableSetting.Total"
        @handle-delete="handleDelete"
        @handle-edit="handleEdit"
        @select-data="currentSelectChange"
        @change-page="changePage"
      >
      <!-- 通过custom方法可以去对table里面某些字段进行特殊处理 -->
        <template slot="custom" v-if="item.custom" slot-scope="{ item, index }">
          <el-table-column
            :prop="item.column_name"
            :label="item.column_comment"
            :key="index + item.column_name"
            :show-overflow-tooltip="item.showTooltip ? item.showTooltip : false"
            :width="item.width"
            :sortable="item.sortable"
          >
            <template slot-scope="scope">
              <span v-if="item.column_name == 'DeviceTypeUid'">
                {{ formatDeviceType(scope.row) }}
              </span>
              <span v-else-if="item.column_name == 'DeviceGroupUid'">
                {{ formatDmpDeviceType(scope.row) }}</span
              >
            </template>
          </el-table-column>
        </template>
        <!-- 可以在当前页面添加特殊按钮的时候可以这么添加 -->
        <template slot="otherBtn" slot-scope="{ scope }">
          <el-button
            size="mini"
            icon="hs hs-web-authority-assignment"
            type="primary"
            @click="handleJurisdiction(scope.$index, scope.row)"
            :disabled="scope.row.UpdateFlag === 0 ? true : false"
          >
            分配權限</el-button
          >
        </template>
      </Table>
    </el-card>
  data() {
    return {
      tableData: {
        loading: false,
        header: [
          {
            id: 1,
            column_name: "name",
            column_comment: "姓名",
            showTooltip: false,
          },
          {
            id: 2,
            column_name: "Code",
            column_comment: "编号",
            showTooltip: false,
            sortable: true,
          },
          {
            id: 3,
            column_name: "DeviceTypeUid",
            column_comment: "设备1",
            showTooltip: false,
            sortable: true, //开启排序
            custom: true,//当custom为true 时就会触发上面那个判断
          },
          {
            id: 4,
            column_name: "DeviceGroupUid",
            column_comment: "设备2",
            showTooltip: false,
            sortable: true,
            custom: true, 
          },
        ],
        list: [
          {
            id: 1,
            name: "test",
            Code: "1",
            DeviceTypeUid: "1",
            DeviceGroupUid: "1",
          },
          {
            id: 2,
            name: "test2",
            Code: "2",
            DeviceTypeUid: "2",
            DeviceGroupUid: "2",
          },
          {
            id: 3,
            name: "test3",
            Code: "3",
            DeviceTypeUid: "3",
            DeviceGroupUid: "3",
          },
        ],
      },
      deviceList: [
        {
          name: "设备1",
          id: "1",
        },
        {
          name: "设备2",
          id: "2",
        },
        {
          name: "设备3",
          id: "3",
        },
      ],
      tableSetting: {
        Total: 3, // 总数
        PageSize: 20, // 每页显示数量
        CurrentPage: 1, // 当前页
      },
    };
  },
 类似资料: