Element el-table 表格二次封装

11,460 阅读2分钟

内容背景

公司开发的管理后台系统需要用到大量的表格数据,每个页面内容大致相同,为了便于后期维护,便考虑将el-table进行封装,将公共部分内容提取出来,后期只需对表格内容进行维护即可。

使用到的技术:

  • vue
  • Element-ui

封装内容

简单来说,就是把el-table中的属性数据显示都是用父组件传进来,都可以自定义。

官方的el-table组件

  • 表格属性:

    项目常用属性:data,显示表格数据;

    height:定义table表格的高度。

    stripe: 表格为斑马纹。

    filter-multiple:数据过滤的选项是否多选。

  • 表格方法:

    row-class-name:行的className回调方法,用来给指定行进行颜色高亮区分。

    sort-change: 当表格的排序条件发生变化的时候会触发该事件。

    filter-change: 表格筛选条件发生变化的时候会触发该事件。

封装表格

<el-table 
    ref="filterTable"
    :row-class-name="tableRowClassName"
    border 
    v-loading="loading"
    element-loading-background="rgba(0, 0, 0, 0.8)"
    :data="tableData" 
    :height="height || undefined"
    :max-height="height || undefined"
    :cell-style="cellStyle"
    :default-sort = "{prop: 'id', order: null}"
    @sort-change="sortChange"
    @filter-change="handleFilterChange"
    style="width: 100%">
    <template v-for="(item, index) in columns">
      <el-table-column
        :show-overflow-tooltip="true"
        v-if="item.show != false" 
        :key="index"
        :sortable="item.sortable"
        :prop="item.prop"
        :label="item.label"
        :align="item.align ? item.align : 'left'"
        :width="item.width"></el-table-column>
        <template v-for="(filter, index) in item.filterColums">
            <!-- 表格内联下拉框样式-->
          <el-table-column
            v-if="filter.type == 'select' && filter.show != false"
            :label="columnLabel[index]"
            :key="filter.lable"
            :prop="filter.prop"
            :show-overflow-tooltip="true"
            :fixed="filter.fixed ? filter.fixed : false"
            :width="filter.width ? filter.width : ''"
            :filter-multiple="multiple"
            :filters="filter.filtersList"
            :filter-method="filterMethod"
            :column-key="filter.prop">
            <template slot-scope="props">
              <el-select
                class="select-row"
                v-if="filter.part == 'sell'"
                v-model="props.row.sell_id"
                placeholder="请选择"
                @change="filterChange(props.row)"
                style="height: 25px;">
                <el-option
                  v-for="filter in filtersList"
                  :key="filter.id"
                  :label="filter.realname"
                  :value="filter.id"
                ></el-option>
              </el-select>
            </template>
          </el-table-column>
        <!-- solt 自定义列-->
        <template v-if="item.type === 'slot'">
          <el-table-column 
            :key="index"
            :width="item.width"
            :prop="item.prop"
            :label="item.label">
            <template slot-scope="scope">
               <slot :name="item.slotType" :row="scope.row" />
            </template>
          </el-table-column>
        </template>
    </template>
    <!-- 表格操作按钮-->
    <el-table-column 
      v-if="tableOption && tableOption.label" 
      :width="tableOption.width" 
      :label="tableOption.label" 
      fixed="right"
      align="center" 
      class-name="small-padding fixed-width">
      <template slot-scope="scope">
        <el-button  
          v-for="(item,index) in tableOption.options" 
          :key="index" 
          :type="item.type" 
          :icon="item.icon" 
          v-show="!scope.row.validStatus"
          @click="handleButton(item.methods,scope.row)" 
          size="mini">
          {{item.label}}
        </el-button>
      </template>
    </el-table-column>
</el-table>

我的项目中有几处需要用到表格内下拉框的情况,所以在这里进行了一个type == 'select'的区别封装,通常使用自定义列即可满足需求,具体情况可按照自己项目进行调整

接下来就是将table中的数据内容暴露出来,供父组件传递数据。如下:

props: {
    tableData: Array,
    tableOption: Object,
    filterColums: Array,
    columns: Array,
    tableRowClassName: Function,
    loading: Boolean,
    filtersList: Array,
    filtersRoleList: Array,
    columnLabel: Array,
    filterMethod: Function,
    cellStyle: Function,
    refTable: String,
    multiple: {
      type: Boolean,
      default: false
    },
    // 监听高度
    listenHeight: {
      type: Boolean,
      default: true
    }
},

数据暴露出来之后,再将方法暴露给父组件,如下:

methods: {
    handleButton(methods, row, event) {
      this.$emit('handleButton',{ 'methods':methods,'row':row })
    },
    filterChange (row) {
      this.$emit('filterChange', row)
    },
    filterRoleChange (row) {
      this.$emit('filterRoleChange', row)
    },
    handleFilterChange (filters) {
      this.$emit('handleFilterChange', filters)
    },
    sortChange (filters) {
      this.$emit('sortChange', filters)
    },
    switchChange (row) {
      this.$emit('switchChange', row)
    },
    rowClick (type, value) {
      this.$emit('rowClick', type, value)
    },
}

以上,表格已经封装完毕,接下来我们开始在项目中使用他吧~

页面使用

 <Table
  :loading="loading"
  :tableData="tableData"
  :table-option="tableOption"
  :columns="tableColumns"
  :columnLabel="softwareLable"
  :filtersList="softwareFiltersList"
  :cellStyle="cellStyle"
  @handleFilterChange="handleFilterChange"
  @handleButton="handleButton">
  <template #enable="scope">
    <el-switch
      active-color="#239656"
      inactive-color="#e86161"
      v-model="scope.row.enable"
      @change="changeSwitch(scope.row, 'enable')">
    </el-switch>
  </template>
</Table>
// tableColumns.js
export const tableColumns = [
  { prop: 'id', label: 'ID', width: 70 },
  { prop: 'name', label: '名称' },
  { prop: 'description', label: '描述'},
  {
    show: false,
    filterColums:[
      { 
        prop: 'software_name', 
        label: '适用软件', 
        type: "text", 
        filtersList: [
          {
            text: '软件1',
            value: 1
          },
          {
            text: '软件2',
            value: 2
          },
          {
            text: '软件3',
            value: 3
          },
          {
            text: '软件4',
            value: 4
          },
          {
            text: '软件5',
            value: 5
          }
        ]
      },
    ]
  },
  { prop: 'price', label: '单价'},
  { prop: 'price_range', label: '价格范围'},
  { prop: 'scale', label: '系数'},
  { show: false, prop: 'enable', label: '可用', type: 'slot', slotType: 'enable'},
]

export const tableOption = {
  label: '操作',
  width: '120',
  options: [
    { label: '', type: 'text', icon: 'el-icon-edit-outline', methods: 'edit' },
    { label: '', type: 'text', icon: 'el-icon-delete', methods: 'delete' },
  ]
}
<script>
import Table from '@/components/myTable/index'
import { tableColumns, tableOption } from './tableColumns'
export default {
  components: {
    Table
  },
  data() {
    return {
      loading: false,
      tableData: [],
      tableOption: tableOption,
      tableColumns: tableColumns,
      softwareLable: ['软件'],
      softwareFiltersList: [],
    }
  },
  methods: {
    getTableData () {
      // 接口数据信息获取
    },
    cellStyle () {
      // 表格行内样式
    },
    handleFilterChange () {
      // 表格筛选方法
    },
    handleButton () {
      // 表格操作方法
    },
    changeSwitch () {
      // Switch 操作方法
    }
  },
}
</script>

以上,完整的项目就可以呈现。对应的一些方法操作可自行添加。 封装不够完美,有什么好的方法欢迎大家一起讨论~