我们开发后台管理系统的时候需要用到大量的表格数据,但是每个页面的结构很一样, 所以有很多重复的表格结构代码,因此便考虑将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},
]
以上,完整的表格就可以呈现。表格还应该有很多操作,单选、多选、排序、多列排序等,这些方法都有在这个基础上进行封装,欢迎大家一起讨论学习~