el-Table组件二次封装

525 阅读1分钟

本次对element-ui的Table组件进行了二次封装,(对应原element-table组件的功能可能有所缺少,使用到的情况下,可以自行添加)

一、大概样子

截屏2023-10-27 14.19.25.png

二、主要代码

<template>
   <div>
      <!-- 头部搜索表单 -->
      <el-form :inline="true" :model="searchParam" class="demo-form-inline">
         <el-form-item v-for="(item, index) in searchList" :key="index" :label="item.labelName">
            <el-input v-model="searchParam[item.param]" v-if="item.searchType == 'input'" :placeholder="item.labelName"></el-input>
            <el-select v-if="item.searchType == 'filterList'" v-model="searchParam[item.param]" :placeholder="item.labelName">
               <el-option :label="filterItem.label" :value="filterItem.value" v-for="(filterItem, filterIndex) in item.filterList" :key="filterIndex"></el-option>
            </el-select>
         </el-form-item>
         <el-button type="primary" @click="getTableData">查询</el-button>
      </el-form>
      <!-- 表格数据,根据传入的参数来判断是否需要选择框、序号等 -->
      <el-radio-group
         :style="{
            width: '100%',
            'margin-top': '10px',
            height: this.$props.height ? this.$props.height : '80%',
         }"
         v-model="selectRow"
         @change="handleRadioGroupChange"
      >
         <el-table
            ref="multipleTable"
            :data="this.$props.data"
            style="font-size: 10px; color: #555555; width: 100%"
            @selection-change="onSelectListChange"
            height="100%"
            border
            :cell-style="ceStyle"
            :header-cell-style="headerStyle"
         >
            <el-table-column :key="0" width="55" fixed="left" align="center" v-if="radio">
               <el-radio slot-scope="scope" :label="scope.row">{{ null }}</el-radio>
            </el-table-column>
            <el-table-column :key="1" type="selection" v-if="select" width="55" align="center"></el-table-column>
            <el-table-column type="index" width="50" label="序号" align="center" fixed="left" :key="2"></el-table-column>
            <template v-for="(column, index) in this.columns">
               <el-table-column v-if="!column.isMerge" :prop="column.param" :key="index + 3" align="center" :label="column.labelName" :width="column.width" :fixed="column.fixed">
                  <div slot-scope="scope" @click="column.cb ? column.cb(scope) : null">
                     <span v-if="!column.filterList">{{ scope.row[column.param] || scope.row[column.param] == "null" ? scope.row[column.param] : "--" }}</span>
                     <span v-else>{{ filterItem(scope.row[column.param], column.filterList).label }}</span>
                  </div>
                  <!-- 合并表头 -->
               </el-table-column>
               <el-table-column :label="column.labelName" align="center" v-else :key="index + 3">
                  <el-table-column
                     v-for="(column_child, index_status) in column.childList"
                     :prop="column_child.param"
                     :width="column_child.width"
                     :label="column_child.labelName"
                     :fixed="column_child.fixed"
                     align="center"
                     :key="index_status"
                  >
                     <div slot-scope="scope" @click="column_child.cb ? column_child.cb(scope) : null">
                        <span
                           :style="{
                              color: filterItem(scope.row[column_child.param], column_child.filterList).color,
                           }"
                           v-if="column_child.filterList"
                        >
                           {{ filterItem(scope.row[column_child.param], column_child.filterList).label }}
                        </span>
                        <span v-else>
                           {{ scope.row[column_child.param] || scope.row[column_child.param] == "null" ? scope.row[column_child.param] : "--" }}
                        </span>
                     </div>
                  </el-table-column>
               </el-table-column>
            </template>
            <slot name="moreColumn"></slot>
         </el-table>
      </el-radio-group>
      <el-pagination
         style="position: absolute; bottom: -50px; right: 40px"
         @size-change="handleSizeChange"
         @current-change="handleCurrentChange"
         background
         :total="total"
         :current-page.sync="searchParam.page"
         :page-size="searchParam.size"
         layout="->,sizes,prev, pager, next, jumper"
      ></el-pagination>
   </div>
</template>

<script>
export default {
   name: "Table",
   props: {
      // 表格高度
      height: {
         type: String,
         require: false,
      },

      //单选radio
      radio: {
         type: Boolean,
         require: false,
      },
      //单选选项发生变化时候调用,参数row
      onRadioChange: {
         type: Function,
         require: false,
      },
      //是否需要选择框
      select: {
         type: Boolean,
         require: false,
      },
      //多选表格数据变化调用,参数rows
      onSelectChange: {
         type: Function,
         require: false,
      },
      //表格数据
      data: {
         type: Array,
         require: false,
      },
      //表单列信息
      columns: {
         type: Array,
         require: false,
      },
      //头部表单样式
      headerCellStyle: {
         type: Object,
         required: false,
      },
      //表单内部表格样式
      cellStyle: {
         type: Object,
         required: false,
      },
      //查询列表数据接口
      handleGetTableData: {
         type: Function,
         required: true,
      },
      //总计多少条
      total: {
         type: Number,
         required: true,
      },
   },
   data() {
      return {
         selectList: [],
         selectRow: {},
         headerStyle: {
            background: "#eeeeee",
            fontWeight: 400,
            color: "#000",
         },
         ceStyle: { height: "45px", color: "#7f7f7f" },
         searchParam: {},
         searchList: null,
         tempSearchParam: { page: 1, size: 10 },
      };
   },
   created() {
      this.searchList = this.columns.filter((item) => !!item.searchType);
      this.searchParam = this.searchList.reduce(
         (acc, key) => {
            console.log(acc, key);
            acc[key.param] = null;
            return acc;
         },
         { page: 1, size: 10 },
      );
      this.getTableData();
   },
   mounted() {
      if (this.headerCellStyle) {
         this.headerStyle = this.headerCellStyle;
      }
      if (this.cellStyle) {
         this.ceStyle = this.cellStyle;
      }
   },

   methods: {
      onSelectListChange(multiples) {
         this.selectList = multiples;
         this.$props.onSelectChange(multiples);
      },
      filterItem(text, type) {
         const item = type.find((k) => k.value === text);
         return item
            ? item
            : {
                 value: null,
                 label: "--",
                 color: "#000",
              };
      },
      handleRadioGroupChange(val) {
         this.$props.onRadioChange(val);
      },
      handleCancelSelect(row, selected) {
         const rowPro = this.$props.data.find((item) => item.xqbm == row.xqbm);
         if (rowPro) this.$refs.multipleTable.toggleRowSelection(rowPro, selected);
      },
      handleSizeChange(val) {
         this.tempSearchParam.size = this.searchParam.size = val;
         this.tempSearchParam.page = this.searchParam.page = 1;
         this.getTableData();
      },
      handleCurrentChange(val) {
         this.tempSearchParam.page = this.searchParam.page = val;
         this.getTableData();
      },
      getTableData() {
         const { page: oldPage, size: oldSize, ...oldRest } = this.tempSearchParam;
         const { page: newPage, size: newSize, ...newRest } = this.searchParam;
         if (JSON.stringify(newRest) != JSON.stringify(oldRest)) {
            this.searchParam.page = 1;
         }
         this.tempSearchParam = JSON.parse(JSON.stringify(this.searchParam));
         this.handleGetTableData(this.tempSearchParam);
      },
   },
};
</script>
<style lang="less" scoped></style>

三、使用

<template>
   <Table
      style="position: relative"
      :select="true"
      :radio="false"
      :data="tableData"
      :total="total"
      :columns="tableColumn"
      :headerCellStyle="{
         background: '#F5F7FA',
         fontWeight: 400,
         color: '#000000b3',
      }"
      :cellStyle="{ background: '#fff', color: '#000000e6' }"
      :onSelectChange="(rows) => onSelectListChange(rows)"
      :handleGetTableData="(param) => handleGetTableData(param)"
   >
      <el-table-column width="160" label="操作" slot="moreColumn" align="center" fixed="right" :key="tableColumn.length + 3">
         <el-button type="text">测试按钮</el-button>
      </el-table-column>
   </Table>
</template>

<script>
import Flex from "@/components/Flex";
import Table from "@/components/Table";
export default {
   name: "HomePage",
   components: { Flex, Table },
   data() {
      return {
         tableData: [
            {
               date: "2016-05-02",
               name: "王小虎",
               address: "上海市普陀区金沙江路 1518 弄",
               zt: 1,
               firstHobby: "哈哈",
               secondHobby: "asd",
            },
            {
               date: "2016-05-04",
               name: "王小虎",
               address: "上海市普陀区金沙江路 1517 弄",
               zt: 3,
               firstHobby: "哈哈",
               secondHobby: "asd",
            },
            {
               date: "2016-05-01",
               name: "王小虎",
               address: "上海市普陀区金沙江路 1519 弄",
               zt: 2,
               firstHobby: "哈哈",
               secondHobby: "asd",
            },
            {
               date: "2016-05-03",
               name: "王小虎",
               address: "上海市普陀区金沙江路 1516 弄",
               zt: 1,
               firstHobby: "哈哈",
               secondHobby: "asd",
            },
         ],
         tableColumn: [
            {
               labelName: "生日",
               param: "date",
            },
            {
               labelName: "姓名",
               param: "name",
               fixed: "left",
               searchType: "input",
               cb: (scope) => console.log(scope.$index),
            },
            {
               labelName: "爱好",
               param: "hobby",
               color: "#6babfc",
               isMerge: true,
               childList: [
                  {
                     labelName: "爱好1",
                     param: "firstHobby",
                     color: "#6babfc",
                     cb: (scope) => console.log(scope),
                  },
                  {
                     labelName: "爱好2",
                     param: "secondHobby",
                     color: "#6babfc",
                     cb: (scope) => console.log(scope),
                  },
               ],
            },
            {
               labelName: "状态",
               param: "zt",
               searchType: "filterList",
               filterList: [
                  {
                     value: 1,
                     label: "测试状态一",
                     color: "#c4c4c4",
                  },
                  {
                     value: 2,
                     label: "测试状态二",
                     color: "#facd91",
                  },
               ],
               width: 80,
            },
         ],
         total: 0,
      };
   },
   created() {},
   methods: {
      handleGetTableData(param) {
         console.log("param", param);
      },
      onSelectListChange(rows) {
         console.log("rows", rows);
      },
   },
};
</script>
<style lang="less" scoped></style>


1、主要通过props传值;

2、相应的props对应的功能以及回调函数都在代码中

3、示例中是缺少接口代码的,需要自己手动修改,并将相关的数据以及对象都修改成自己的即可使用

4、column:类型[{labelName:'',param:'',fixed:'',...otherType}]

        1)、labelName:列名

        2)、param:列对应的字段

        3)、fixed:同elementui里的用法

        4)、searchType:搜索框的样式(目前我只添加了filterList与input,需要更多其他样式可以自行添加使用,注意:使用filterList字符时候需要添加filterList属性,格式为[{value:'',label:''}])

        5)、isMerge:布尔类型,是否合并表头,(注意:使用该属性时候,如果为true,需要添加childList属性,类型同column的类型)

        6)、cb:(scope)=>{},为点击每一个格子的点击事件,scope即column的row