el-table的二次封装

背景


我们开发后台管理系统的时候需要用到大量的表格数据,但是每个页面的结构很一样, 所以有很多重复的表格结构代码,因此便考虑将el-table进行二次封装,将公共的内容提取出来,用数据来驱动表格。


使用到技术
  • Vue
  • Element-ui

官方的el-table组件

<el-table
    :data="tableData"
    border
    class="table"
    ref="multipleTable"
    header-cell-class-name="table-header"
    @selection-change="handleSelectionChange"
>
    <el-table-column 
        type="selection"
        width="55" 
        align="center">
    </el-table-column>
    <el-table-column 
        prop="id" 
        label="ID" 
        width="55" 
        align="center">
    </el-table-column>
    <el-table-column 
        prop="Category"
        label="产品名称">
    </el-table-column>
    <el-table-column 
        prop="url"
        label="图片路径">
    </el-table-column>
    <el-table-column 
        prop="brief" 
        label="产品简介">
    </el-table-column>
    <el-table-column 
        prop="brand" 
        label="产品品牌">
    </el-table-column>
    <el-table-column 
        prop="specs" 
        label="产品规格">
    </el-table-column>
    <el-table-column 
        prop="price" 
        label="产品价格">
    </el-table-column>
    <el-table-column 
        label="操作"
        width="180"
        align="center">
        <template slot-scope="scope">
            <el-button type="text" icon="el-icon-edit" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
            <el-button type="text" icon="el-icon-delete" class="red" @click="handleDelete(scope.$index, scope.row)"删除</el-button>
        </template>
    </el-table-column>
</el-table>
<div class="pagination">
    <el-pagination
        background
        layout="total, prev, pager, next"
        :current-page="query.pageIndex"
        :page-size="query.pageSize"
        :total="pageTotal"
        @current-change="handlePageChange"
    ></el-pagination>
</div>

一个el-table-column标签就是表格的一列,如果表格内容多的话,会导致重复的代码很多。


封装方法

简单来说,就是将el-table中的属性数据都由父组件传递进来,当作表格的配置,来渲染表格。同时要支持多种显示方式,因为表格可能不光只是展示一个纯数据,有可能是图片或者其他内容,可以通过插槽来实现。


封装表格

<template>
  <div>
    <div class="table-box w100 show-flex-grow-1">
      <el-table
        class="w100"
        height="100%"
        header-row-class-name="custom-header-row"
        :data="tableData.items"
        tooltip-effect="dark"
        empty-text="暂无数据"
        :stripe="stripe"
        :border="border"
      >
      	<!-- 序号 -->
        <el-table-column
          v-if="showIndexColumn"
          type="index"
          :label="index"
          align="center"
          width="70"
        />
        <!-- 通过配置数组渲染表格的列 -->
        <template v-for="(item, index) in propList">
          <el-table-column
            :key="index"
            :align="item.align || 'center'"
            v-bind="item"
            :prop="item.prop || ''"
            :label="item.label"
          >
          <!-- 头部插槽,一般用来放筛选组件 -->
            <template slot="header" v-if="item.hasFilter">
              <slot :name="item.filterField"></slot>
            </template>
			<!-- 表格列,可自定义显示的内容 -->
            <template slot-scope="{ row }">
              <!-- #default="{ row }" -->
              <slot :name="item.slotName" :row="row">
                <span>{{ typeof row[item.prop] === 'number'
                  ? row[item.prop] || 0
                  : row[item.prop] || '---' }}</span>
              </slot>
            </template>
          </el-table-column>
        </template>
      </el-table>
    </div>
	<!-- 分页器,二次封装过后的组件 -->
	<div>
      <pagination
        :total="tableData && tableData.total"
        :showRecods="tableData && tableData.items && tableData.items.length"
        :current-page="page"
        :cur-limit="limit"
        @post-curNOP="recieveCurNOP"
        @post-curlimit="recieveCurLimit"
      />
    </div>
  </div>
</template>
<script>
import pagination from '@/components/show-ui/pagination-comp';

export default {
  components: {
    pagination,
  },
  props: {
    page: {
      type: Number,
      default: 1
    },
    limit: {
      type: Number,
      default: 10
    },
    stripe: {
      type: Boolean,
      default: false
    },
    border: {
      type: Boolean,
      default: false
    },
    showIndexColumn: {
      type: Boolean,
      default: false
    },
    showSelectionColumn: {
      type: Boolean,
      default: false
    },
    tableData: {
      type: Object,
      default: () => {
        return {
          total: 0,
          items: [],
        }
      }
    },
    propList: Array,
    showPagination: {
      type: Boolean,
      default: true
    },
  },
  data() {
    return {};
  },
  methods: {
    rowClick(row){
      const info = {
        type: 'row-click',
        data: {...row}
      };

      this.sendInfo(info, 'handle-table');
    },
    // 分页
    recieveCurNOP(curNOP){
      const info = {
        type: 'pagination',
        page: curNOP,
        limit: this.limit,
      };

      this.sendInfo(info, 'handle-page');
    },
    // 分页
    recieveCurLimit(curLimit){
      const info = {
        type: 'pagination',
        page: this.page,
        limit: curLimit,
      };

      this.sendInfo(info, 'handle-page');
    },
    // 抛出函数
    sendInfo(info, func = 'clickInfo'){
      this.$emit(func, info);
    },
  },
}
</script>

以上,表格就已经封装完毕,接下来让我们来看一下是如何使用的吧~


组件的使用

<basic-table
  key="table-article2"
  :table-data="tableListData"
  :page="page"
  :limit="limit"
  :showIndexColumn="true"
  :prop-list="propConfig"
  @handle-page="handlePage"
>
  <!-- 配置数组里规定的插槽的名字, 用来自定义表格展示内容 -->
  <template #TitlePage="{ row }">
    <div class="custom-item">
      <img :src="row.cover_url" />
    </div>
  </template>
  <template #ArticleStatus="{ row }">
    <div class="custom-item ticket-status-content">
      <!-- 这是需要根据状态展示不同的圆点和文案 -->
      <div
        :style="{ background: getCircleBgColor(row.status) }"
      ></div>
      <span class="table-span">{{
      	getStatusTitle(row.status)
      }}</span>
    </div>
  </template>
  <template #CreateTime="{ row }">
    <span>{{ row.created_at | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
  </template>
  <template #ArticleAction="{ row }">
    <div class="table-action-align">
      <span
        @click="editAction(row, 'guidelines')"
        class="user-action"
        v-if="row.status == '0'"
        >编辑</span>
      <span
        @click="soldOutAction(row)"
        class="user-action"
        v-if="row.status == '2'"
        >下架</span>
      <span
        @click="groundAction(row, 'guidelines')"
        class="user-action"
        v-if="row.status == '0'"
        >上架</span>
      <span 
      	@click="seeAction(row, 'guidelines')"
      	class="user-action">查看</span>
      <span
        @click="deleteAction(row)"
        class="user-action"
        v-if="row.status == '0'">删除</span>
    </div>
  </template>
</basic-table>

这里就不展示上面用到的方法了,重要的是表格的两个配置数组,一个是propConfig属性数组,另一个就是用来展示数据的tableListData数组。

// 配置数组
propConfig: [
  { prop: "name", label: "ArticleName" },
  { prop: "cover_url", label: "TitlePage", slotName: "TitlePage" },
  {
    prop: "status",
    label: "ArticleStatus",
    slotName: "ArticleStatus",
  },
  { prop: "created_at", label: "CreateTime", slotName: 'CreateTime'},
  {
    prop: "ArticleAction",
    label: "ArticleAction",
    slotName: "ArticleAction",
    width: 200,
  },
],
// 数据数组
tableListData: [
	{name: '测试文章1', cover_url: 'xxxxxxx', status: 0, created_at: 1667112277},
	{name: '测试文章2', cover_url: 'xxxxxxx', status: 1, created_at: 1667112277},
	{name: '测试文章3', cover_url: 'xxxxxxx', status: 2, created_at: 1667112277},
]

以上,完整的表格就可以呈现。表格还应该有很多操作,单选、多选、排序、多列排序等,这些方法都有在这个基础上进行封装,欢迎大家一起讨论学习~

你可能感兴趣的:(javascript,前端,elementui)