最近接手了一个后台项目,需要给这个项目添加新的功能。发现之前的表格写法都是跟element官网的案例一样的写法

axios二次封装取消请求 二次封装element_前端

这种写法下,如果表格有多个列的情况下就得写很多个el-table-column,而且如果说字段值为空的情况下显示‘--’就得一个一个去写,做很多重复的工作,于是我决定将表格进行二次封装。

封装思路:

  1. 使用循环去生成每一个表格列
  2. 判断表格列是否需要插槽,需要插槽的话要定义一个slot并且需要将每一行的数据返回给外层组件使用
  3. 判断需要使用的表格列类型,例如文本型或者数字型,在值为空的情况下处理显示文字
  4. 配合element的分页器进行表格分页处理 
  5. 引入表格组件传递表格配置参数
<template>
  <div class="table-box">
    <el-table
      v-loading="tableLoading"
      element-loading-text="拼命加载中..."
      :data="tableData"
      style="width: 100%;"
      :row-key="rowId"
      :tree-props="{children: 'details', hasChildren: 'hasChildren'}"
      :default-sort="sortRule"
      :show-summary="isShowSummary"
      :summary-method="getSummaries"
    >
    <el-table-column type="expand" v-if="isShowExpand">
      <template slot-scope="scope">
            <slot name="expand" :rowData="scope"></slot>
      </template>
    </el-table-column>
      <el-table-column
        v-for="(coloum,index) in coloumData"
        :key="index"
        :width="coloum.width"
        :label="coloum.label"
        :fixed="coloum.fixed?coloum.fixed:false"
        :sortable="coloum.showSort"
        :sort-by="coloum.sortName"
        align="center"
      >
        <template slot-scope="scope">
          <div v-if="coloum.slot">
            <slot :name="coloum.slot" :rowData="scope"></slot>
          </div>
          <div v-else-if="coloum.type === 'text'">
            {{ scope.row[coloum.prop] || '--' }}
          </div>
          <div v-else-if="coloum.type === 'number'">
            {{ scope.row[coloum.prop] || 0 }}
          </div>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-if="isShowPagination"
      :current-page="paginationParam.currentPage"
      :page-size="paginationParam.size"
      :page-sizes="paginationParam.sizes"
      layout="total, sizes, prev, pager, next, jumper"
      :total="paginationParam.total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    ></el-pagination>
  </div>
</template>
  
  <script>
export default {
  name: "tableModule",
  props: {
    // 表格列表
    tableData: {
      type: Array,
      require: true
    },
    // 表格头参数
    coloumData: {
      type: Array,
      require: true
    },
    // 开启子集需要的key
    rowId: {
      type: String
    },
    // 排序规则
    sortRule: {
      type: Object
    },
    // 分页器的参数
    paginationParam: {
      type: Object
      // eslint-disable-next-line vue/require-valid-default-prop
    },
    // 是否显示分页器
    isShowPagination: {
      type: Boolean,
      default: true
    },
    // 是否显示合计
    isShowSummary: {
      type: Boolean,
      default: false
    },
    // 合计函数
    getSummaries: {
      type: Function
    },
    // 表格加载
    tableLoading: {
      type: Boolean,
      default: false
    },
    // 表格第一项是否展开标签
    isShowExpand:{
      type: Boolean,
      default: false
    }
  },
  methods: {
    // 修改分页大小
    handleSizeChange(e) {
      this.$emit("changeSize", e);
    },
    // 修改当前页码
    handleCurrentChange(e) {
      this.$emit("changePage", e);
    }
  }
};
</script>
  
<style lang="scss" scoped>
::v-deep .el-table td.el-table__cell div {
  display: flex;
  justify-content: center;
  align-items: center;
}
::v-deep .el-pagination {
  margin-top: 16px;
  text-align: right;
}
</style>
<template>
   <app-table
        :tableData="inventoryReportData"
        :coloumData="tabColumn"
        :sortRule="{ prop: 'stock_date', order: 'descending' }"
        :paginationParam="paginationParam"
        @changeSize="changeSize"
        @changePage="changePage"
     >
        // #后面的变量需要跟tabColumn中的slot属性的值匹配上,案例中还有几个插槽,不一一展示,看最终效果就行
        <template #storage="{rowData}">
           {{ rowData.row.s_num + rowData.row.unit_name }}
            <br />
           {{ rowData.row.s_weight + 'kg' }}
        </template>
    </app-table>
</template>
<script>
// 我的table组件做成了全局组件所以直接使用就行,如果没有做成全局的话需要引入table组件
export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: "GoodsList",
  data() {
    return {
      // 表格数据
      inventoryReportData: [],
      // 表格头
      tabColumn: [
        {
          // 文本类型
          type: "text",
          // 表格头文字
          label: "入库日期",
          // 取值字段
          prop: "stock_date",
          // 是否展示排序
          showSort: true,
          // 排序的字段名称
          sortName: "stock_date",
          // 表格宽度,不设置默认自适应
          width: 120
        },
        {
          type: "text",
          label: "商户名称",
          prop: "customer_name"
        },
        {
          type: "text",
          label: "商品名称",
          prop: "goods_name"
        },
        {
          type: "text",
          label: "商品分类",
          prop: "gc_name_1"
        },
        {
          type: "text",
          label: "柜号",
          prop: "container_no"
        },
        {
          slot: "available",
          label: "可用商品库存",
          width: 150
        },
        {
          slot: "freeze",
          label: "冻结商品库存",
          width: 150
        },
        {
          slot: "general",
          label: "总商品库存",
          width: 150
        },
        {
          slot: "settlement",
          label: "待结算商品库存",
          width: 150
        },
        {
          // 插槽模式,不需要配置prop
          slot: "origin",
          label: "商品来源"
        },
        {
          type: "text",
          label: "商品批号",
          prop: "batch_no"
        },
        {
          type: "text",
          label: "生产日期",
          prop: "mfg_date"
        },
        {
          type: "text",
          label: "过期日期",
          prop: "exp_date"
        },
        {
          slot: "operate",
          label: "操作"
        }
      ],
      // 分页数据
      paginationParam: {
        currentPage: 1,
        size: 10,
        sizes: [10, 20, 50, 100],
        total: 400
      }
    };
  },
  methods: {
    // 获取数据
    getList(){
        ......
        this.inventoryReportData = res.data
    }
  }
}
</script>

axios二次封装取消请求 二次封装element_javascript_02

 这就是表格的简单用法,表格中还有很多其他的配置,可以看看上面的table组件,如果还需要增加其他功能可以参考element文档对table组件进行修改。