最近接手了一个后台项目,需要给这个项目添加新的功能。发现之前的表格写法都是跟element官网的案例一样的写法
这种写法下,如果表格有多个列的情况下就得写很多个el-table-column,而且如果说字段值为空的情况下显示‘--’就得一个一个去写,做很多重复的工作,于是我决定将表格进行二次封装。
封装思路:
- 使用循环去生成每一个表格列
- 判断表格列是否需要插槽,需要插槽的话要定义一个slot并且需要将每一行的数据返回给外层组件使用
- 判断需要使用的表格列类型,例如文本型或者数字型,在值为空的情况下处理显示文字
- 配合element的分页器进行表格分页处理
- 引入表格组件传递表格配置参数
<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>
这就是表格的简单用法,表格中还有很多其他的配置,可以看看上面的table组件,如果还需要增加其他功能可以参考element文档对table组件进行修改。