preface

If the business table is large, the template is not compact enough, and the template columns are not reusable. So consider using columns to dynamically render configuration columns.

  1. Columns array, flexible
  2. Template is a simple, regular table with a single label
  3. Dynamic column logic processing directly programmatic processing, code structure is clear

Packaging ideas

Each of the following uses the EleTable name for the encapsulated Table component.

1. The Table properties

In line with the el-table attribute, use v-bind=”$attrs” to bind the columns attribute.

<EleTable
  :columns="tableColumns"
  :data="tableData"
  border
>
  <template #action="{ row }">
    <TableExportButton
      :row="row"
      @export-action="handleExportAction"
    ></TableExportButton>
  </template>
</EleTable>
Copy the code

2. List of attributes

V -for=”item in columns” v-bind=”item” v-bind=”item” v-bind=”item” v-bind=”item”

export const columns = [
  {
    prop: 'id'.label: 'ID'
  },
  {
    prop: 'name'.label: 'Name of School'
  },
  {
    prop: 'action'.slotName: 'action'.label: 'Name of School'},]Copy the code

Here we consider scenarios where slot is required, so we add slotName to the column, which is used by the component to determine whether slot needs to be rendered

<! - application - >
EleTable
  <template #action="{ row }"></template>
Copy the code

Processing in components:

<template v-if="item.slotName" v-slot:default="scope">
  <! -- column default slot @bind current scope -->
  <slot :name="item.slotName" v-bind="scope" />
</template>
Copy the code

3. loading

Use table loading to achieve universal loading effect, simplify application writing, and directly load the interface

<! -- EleTable.vue -->
<el-table
  v-loading="loading"
  element-loading-text="Data is loading..."
  element-loading-spinner="el-icon-loading"
>
</el-table>

<! -- use.vue -->
<EleTable
  :columns="tableColumns"
  :data="tableData"
  border
  :loading="loading"
/>
Copy the code

4. Paging

Built-in pagination, which can be enabled with Paginate, is consistent with el-Pagination to reduce learning costs.

<el-pagination
  v-if="paginat"
  :total="total"
  :page-sizes="pageSizes"
  :page-size.sync="scopePagesize"
  @size-change="handlePageSizeChange"
  @current-change="handleCurrentPageChange"
  :current-page.sync="scopePage"
  :layout="layout"
></el-pagination>
Copy the code

Use as follows:

 <EleTable
  :columns="tableColumns"
  :data="tableData"
  paginat
  :total.sync="total"
  :page.sync="page"
  :page-size="pageSize"
  :loading="loading"
  border
  @load-data="fetchTableData"
/>
Copy the code

In EleTable, page-related events emit a load-data with {page, pagesize} and update the page\ Pagesize of the outer binding.

this.$emit('load-data', paginationModel);
Copy the code

subsequent

In practice, nested table headers and slot customization of table headers are not supported

The head slot.

Add the headerSlotName attribute

<template
  v-if="item.headerSlotName"
  :slot="item.headerSlotName ? 'header' : null"
  slot-scope="scope"
>
  <! -- column header slot @bind current scope -->
  <slot :name="item.headerSlotName" v-bind="scope" />
</template>
Copy the code

Nested in the head

Considering the basic nesting of a layer and the configuration of a single column of columns, add the Nest attribute, which is roughly as follows:

<el-table-column
  v-if="item.nest"
  :key="customkey ? item[customkey] : index"
  :label="item.label"
  v-bind="item"
>
  <! Nesting with slot mode -->
  <template v-if="item.nest === 'slot'">
    <! -- Nested slot @bind current column -->
    <slot :name="item.nestSlotName" v-bind="item" />
  </template>
  <! -- Use array nesting, only one layer can be nested -->
  <template v-else-if="item.nestColumns && item.nestColumns.length">
    <el-table-column
      v-for="(nestItem, nestIndex) in item.nestColumns"
      :key="nestItem[customkey] || nestIndex"
      :label="nestItem.label"
      v-bind="nestItem"
    >
      <template
        v-if="nestItem.headerSlotName"
        :slot="nestItem.headerSlotName ? 'header' : null"
        slot-scope="scope"
      >
        <! Bind scope of current column -->
        <slot :name="nestItem.headerSlotName" v-bind="scope" />
      </template>
      <template v-if="nestItem.slotName" v-slot:default="scope">
        <! Default slot@bind Current scope -->
        <slot :name="nestItem.slotName" v-bind="scope" />
      </template>
    </el-table-column>
  </template>
  <template v-slot:default="scope">
    {{ item.nest }}
    <! -- Nested column default slot@bind current scope -->
    <slot :name="item.nestSlotName" v-bind="scope" />
  </template>
</el-table-column>
Copy the code

It’s almost done.

Thanks for reading and welcome to the discussion