Super easy to use element’s el-table table component secondary packaging – with source code and explanation

Foreword: In the development of many backend management systems, there are always a lot of tables used. If we use the el-table on the elementui official website to write every time, it will be very troublesome to adjust the styles of all tables, and the page content will also be inconsistent. It would be cumbersome and cumbersome.

Tell me about a secondary encapsulation el-table component that I often use. This component can accommodate many specific needs and is very simple. All examples use vue2 + elementUI. If you want to use vue3 with slight modifications, you can also ask me in the comments

Upload the code directly:

1. Component code

<template>
  <el-table
    ref="multipleTable"
    v-loading="tableLoading"
    :data="tableData"
    element-loading-text="Loading desperately"
    :height="height"
    element-loading-spinner="el-icon-loading"
    element-loading-background="rgba(20, 60, 133, 0.8)"
    tooltip-effect="dark"
    style="width: 100%; "
    border
    :row-class-name="rowClassName"
    :header-cell-style="{ background: '#0e3372', color: '#cccccc' }"
    stripe
    @selection-change="handleSelectionChange"
  >
    <template v-if="isSelection">
      <el-table-column type="selection" width="55" />
    </template>

    <template v-for="(item,index) in column">
      <el-table-column
        :key="index"
        :label="item.label"
        :prop="item.prop"
        :type="item.type"
        :width="item.width"
        :fixed="item.fixed"
        :sortable="item.sortable?true:false"
        :filters="item.filters"
        :column-key="item.columnKey"
        :filtered-value="item.filteredValue"
        :filter-multiple="item.filterMultiple"
        :min-width="item.minWidth"
        align="center"
      >

        <!-- <div class="123" v-if="item.type == ''"> -->
        <template v-if="item.hasOwnProperty('colunmTemplate')" :slot="item.colunmTemplate" slot-scope="scope">
          <slot v-if="item.theadSlot" :name="item.theadSlot" :row="scope.row" :index="index" />
        </template>

        <template slot-scope="scope">
          <!-- slot -->
          <div v-if="item.dataType == 'slot'">
            <slot v-if="item.slot" :name="item.slot" :row="scope.row" :index="scope.$index" />
          </div>


          <!-- Progress bar -->
          <div v-else-if="item.dataType == 'progress'">
            <el-progress :percentage="Number(scope.row[item.prop])" />
          </div>

          <!-- tag -->
          <div v-else-if="item.dataType == 'tag'">

            <el-tag v-if="typeof dataTypeFn(scope.row[item.prop],item.formatData) == 'string'" :title="scope.row[item.prop] | formatters (item.formatData)" :type="formatType(scope.row[item.prop],item.formatType)">
              {<!-- -->{ scope.row[item.prop] | formatters(item.formatData) }}
            </el-tag>

            <el-tag v-for="(tag,index) in dataTypeFn(scope.row[item.prop],item.formatData)" v-else-if="typeof dataTypeFn(scope.row[item. prop],item.formatData) == 'object'" :key="index" :title="scope.row[item.prop] | formatters(item.formatData)" :type=\ "formatType(tag,item.formatType)">
              {<!-- -->{ item.tagGroup ? tag[item.tagGroup.label]?tag[item.tagGroup.label]:tag : tag }}
            </el-tag>

            <el-tag v-else :title="scope.row[item.prop] | formatters(item.formatData)" :type="formatType(scope.row[item.prop],item.formatType)\ ">
              {<!-- -->{ scope.row[item.prop] | formatters(item.formatData) }}
            </el-tag>

          </div>

          <!-- button -->
          <div v-else-if="item.dataType == 'option'">
            <el-button
              v-for="(o, key) in item.operation"
              v-show="o.showHide?o.showHide(scope.row):true"
              :key="key"
              :icon="o.icon | iconFn(scope.row)"
              :disabled="o.disabled?o.disabled(scope.row):false"
              :plain="o.plain"
              :type="o.type | typeFn(scope.row)"
              :size="o.size"
              @click="o.clickFun(scope.row)"
            >
              {<!-- -->{ o.name }}
               </el-button>
          </div>

          <!-- -->

          <!-- Default is pure display data -->
          <div v-else>
            <span v-if="!item.formatData">{<!-- -->{ scope.row[item.prop] }}</span>
            <span v-else>{<!-- -->{ scope.row[item.prop] | formatters(item.formatData) }}</span>
          </div>

        </template>

        <!-- </div> -->

      </el-table-column>
    </template>

  </el-table>
</template>

<script>
export default {
  filters: {
    iconFn(val, row) {
      if (typeof (val) === 'function') {
        return val(row)
      } else return val
    },
    typeFn(val, row) {
      console.log(val,row,'11111111');
      if (typeof (val) === 'function') {
        return val(row)
      } else return val
    },
    describeConts(val, describeCont) {
      if (typeof (describeCont) === 'function') {
        return describeCont(val)
      } else return val
    },
    formatters(val, format) {
      if (typeof (format) === 'function') {
        return format(val)
      } else return val
    }
  },
  props: {
    isSelection: {
      type: Boolean,
      default: false
    },
    height: {
      type: Number,
      default: null
    },
    tableLoading: {
      type: Boolean,
      default: false
    },
    handleSelectionChange: {
      type: Function,
      default: () => {
        return () => {}
      }
    },
    headerCellStyle: {
      type: Object,
      default: () => {
        return {}
      }
    },
    column: {
      type: Array,
      default() {
        return [
        ]
      }
    },
    rowClassName: {
      type: Function,
      default: () => {

      }
    },
    tableData: {
      type: Array,
      default() {
        return []
      }
    }
  },

  methods: {
    formatType(val, format) {
      if (typeof (format) === 'function') {
        return format(val)
      } else return ''
    },
    dataTypeFn(val, format) {
      if (typeof (format) === 'function') {
        return format(val)
      } else return val
    }
  }
}
</script>

<style scoped>
span{
  white-space: pre-wrap;
}
  /* .el-table .warning-row {
    background: oldlace;
  }

  .el-table .success-row {
    background: #f0f9eb;
  } */

/* .app-container /deep/ .el-table, .el-table__expanded-cell {
  background-color: transparent;
}

.app-container /deep/ .el-table tr {
  background-color: transparent!important;
}
.app-container /deep/ .el-table--enable-row-transition .el-table__body td, .el-table .cell{
  background-color: transparent;
} */
</style>

I won’t go into the details inside the component one by one. If you want to know how to write it, if you read it carefully, you will actually know what parameters to pass and how to use them. But if beginners are not familiar with father-son parameter transfer and want to use this component quickly, continue reading.

2. How to use this component

1. Import the component first
import TableCom from '@/components/Table/index'

Don’t forget to register the TableCom you imported in components.

 components: {TableCom},
2. Then write the component in html as shown below
<TableCom
        :column="columnData"
        :table-data="tableData"
        :table-loading="tableLoading"
      >
</TableCom>

Note:

column: Configuration items of each column (column name, size, slot, etc.), type: Array

tabledata: table data (generally an array passed from the backend, with objects in the array), type: array Arrary

tableLoading: loading process display, type: boolean

headerCellStyle: Header color setting, type: Object

3. ColumnData example data:
(A four-column table will be rendered here, each column is name, activation status, protocol, and operation)
columnData: [
        {
          type: '',
          label: 'name',
          prop: 'name'
        },
        {
          type: '',
          label: 'Enabled status',
          prop: 'is_active',
          formatData: (item) => {
            const str = item == true ? 'Enabled' : 'Not enabled'
            return str
          }
        },
        {
          type: '',
          label: 'Protocol',
          prop: 'protocol',
          dataType: 'slot',
          slot: 'protocolSlot'
        },
        {
          dataType: 'option',
          label: 'operation',
          width: '300px',
          operation: [
            {
              name: 'edit',
              type: '',
              size: 'mini',
              icon: 'el-icon-edit',
              plain: true,
              showHide: (row) => {
              },
              clickFun: (row) => {
              }
            },
            {
              name: 'delete',
              type: 'danger',
              size: 'mini',
              showHide: (row) => {
              },
              icon: 'el-icon-delete',
              plain: true,
              clickFun: (row) => {
              }
            }

          ]

        }
      ],

//Table data
tableData: [{name:111,is_active:true,protocol:'TCP'},
{name:111,is_active:true,protocol:'TCP'},
{name:111,is_active:true,protocol:'TCP'}],

Note: The following are all configuration items, the most commonly used ones are label, width, prop, dataType, slot

  1. label: column name, which is what the label on the header is called, type string
  2. width: width of the column, string
  3. prop: table binding data field string, which field in tableData should be displayed in this column
  4. dataType: Built-in multiple basic element components for direct use string
  5. slot When `dataType` is `slot`, a parameter is required. The parameter value is the `slot` value string of the slot. For specific usage methods, please see point 4 below: Use of slot slots
  6. fixed: Whether the column is fixed on the left or right, true means fixed on the left string, boolean
  7. sortable Whether the corresponding column can be sorted boolean, string
  8. filters Data filtering options, array format, elements in the array need to have text and value attributes. Array
  9. columnKey: the key of the column. If you need to use the filter-change event, you need this attribute to identify which column is the filter condition
  10. filteredValue The selected data filtering item. If you need to customize the rendering method of header filtering, you may need this attribute.
  11. filterMultiple Whether the data filtering options are multiple-selectable
  12. minWidth corresponds to the minimum width of the column. The difference from width is that width is fixed, and min-width will proportionally distribute the remaining width to the column string for which min-width is set
  13. formatData performs data processing on the data and accepts a callback function (params?: {prop}) => {}
  14. formatType When `dataType` is `tag`, set the tag color (params?: {prop}) => { return ‘danger’| ‘success’… }`
  15. operation When `dataType` is `option`, the configuration of the button, the specific configuration items are subject to the following figure object
  16. tagGroup When `dataType` is `tag`, the bound data set field displays the name object
4. How to use slots

For example, in the protocol column we just gave an example, our need may not only be to display a protocol, but also to design it in a tag style, then we need to use slots, as shown below, and set the dataType to ‘slot’. Then you can set the slot to the slot name you want. This name is used in HTML.

Then we add the content of the slot to the original component in html:

<TableCom
        :column="columnData"
        :table-data="tableData"
        :table-loading="tableLoading"
      >
 <div
     slot="protocolSlot"
     slot-scope="scope"
    >
        <el-tag>{<!-- -->{scope.row.protocol}}</el-tag>
</div>
</TableCom>

Note: The slot of the div here is the slot name you just obtained in the column, and then you can write any style in it or directly use the components in elementUI. When you want to use data, you can use scope.row.XXX, which is still displayed here. The field of the protocol, so protocol is used, which corresponds to the field in the previous example data tableData.

5. Use formatData for data processing

The following is the example data we just used:

 {
          type: '',
          label: 'Enabled status',
          prop: 'is_active',
          formatData: (item) => {
            const str = item == true ? 'Enabled' : 'Not enabled'
            return str
          }
        },

This is mainly used for the data passed to us by the backend. We do not display it directly. It needs to change according to the data. For example, is_active in tableDate contains true and false, but to display enabled and unenabled, you need to use to formData

6. Other parameters that can be used in dataType

In addition to the slot mentioned in the fourth point above, you can also use tag (label item), progress (progress bar), and option (button configuration item). You can try tag and progress progress bars yourself.

7. Operation configuration

The operation configuration is mainly used for the operation column in the table. There are usually many buttons with the following parameters:

name: button name, string

type: button type, `string` | `danger | success`, subject to elementUi parameter

size: button size, subject to elementUi parameter

icon: icon on the button, subject to elementUi parameter

plain: subject to elementUi document

clickFun: callback function of the button

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Vue entry-level skills treeVue componentsGlobal and local components 39477 people are learning the system