前言
模板中写的话,如果业务表格很多,template不够简洁,而且模板列也不能很好的做到复用。所以考虑到使用columns来动态渲染配置列。
- columns数组,灵活
- template中写法简洁,常规简单表格,就一个标签
- 动态列逻辑处理直接编程式处理,代码结构清晰
封装思路
下面都以EleTable来命名封装的Table组件。
1. Table属性
与el-table属性保持一致,通过v-bind="$attrs"来绑定,增加columns属性。
<EleTable
:columns="tableColumns"
:data="tableData"
border
>
<template #action="{ row }">
<TableExportButton
:row="row"
@export-action="handleExportAction"
></TableExportButton>
</template>
</EleTable>
2. 列属性
列属性保持和el-table-column一致,直接通过v-for="item in columns"结合v-bind="item"来绑定数组中的属性,columns配置实例:
export const columns = [
{
prop: 'id',
label: 'ID'
},
{
prop: 'name',
label: '学校名称'
},
{
prop: 'action',
slotName: 'action',
label: '学校名称'
},
]
这里我们考虑到需要slot的场景,所以在列里增加slotName,组件中通过此属性来判断是否需要渲染slot
<!-- 应用 -->
EleTable
<template #action="{ row }"></template>
组件中处理:
<template v-if="item.slotName" v-slot:default="scope">
<!-- 列default slot
@bind 当前的scope
-->
<slot :name="item.slotName" v-bind="scope" />
</template>
3. loading
使用表格的loading实现通用的加载效果,简化应用写法,直接loading接口
<!-- EleTable.vue -->
<el-table
v-loading="loading"
element-loading-text="数据正在加载中..."
element-loading-spinner="el-icon-loading"
>
</el-table>
<!-- use.vue -->
<EleTable
:columns="tableColumns"
:data="tableData"
border
:loading="loading"
/>
4. 分页
内置分页,可以通过paginate来启用,与el-pagination的属性一致,减少使用学习成本。
<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>
使用的时候如下:
<EleTable
:columns="tableColumns"
:data="tableData"
paginat
:total.sync="total"
:page.sync="page"
:page-size="pageSize"
:loading="loading"
border
@load-data="fetchTableData"
/>
分页数据加载方法如上load-data,传入接口调用方法,在EleTable中,分页的相关事件都会emit一个load-data,携带{ page, pagesize },并会同时update掉外层绑定的page\pageSize。
this.$emit('load-data', paginationModel);
后续
实际应用中,不支持嵌套表头,以及表头的slot自定义
头部slot
增加headerSlotName属性
<template
v-if="item.headerSlotName"
:slot="item.headerSlotName ? 'header' : null"
slot-scope="scope"
>
<!-- 列header slot
@bind 当前的scope
-->
<slot :name="item.headerSlotName" v-bind="scope" />
</template>
嵌套头部
考虑到基本嵌套一层,并在columns的配置单列中,增加nest属性,大致如下:
<el-table-column
v-if="item.nest"
:key="customkey ? item[customkey] : index"
:label="item.label"
v-bind="item"
>
<!-- 使用slot模式进行嵌套 -->
<template v-if="item.nest === 'slot'">
<!--嵌套slot
@bind 当前的column
-->
<slot :name="item.nestSlotName" v-bind="item" />
</template>
<!-- 使用数组嵌套,只能嵌套一层 -->
<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"
>
<!-- 嵌套子列的header slot
@bind 当前列的scope
-->
<slot :name="nestItem.headerSlotName" v-bind="scope" />
</template>
<template v-if="nestItem.slotName" v-slot:default="scope">
<!-- 嵌套子列的内容default slot
@bind 当前scope
-->
<slot :name="nestItem.slotName" v-bind="scope" />
</template>
</el-table-column>
</template>
<template v-slot:default="scope">
{{ item.nest }}
<!-- 嵌套列的default slot
@bind 当前的scope
-->
<slot :name="item.nestSlotName" v-bind="scope" />
</template>
</el-table-column>
基本上完成了。
感谢阅读,欢迎讨论~