实现的功能:表格列渲染(formatter、render)、操作(插槽)、表格多选、筛选、排序,分页组件。
页面效果:
封装后的Table组件代码如下:
<template>
<div>
<el-table
fit
:data="tableData"
style="width: 100%"
highlight-current-row
@sort-change="sortChange"
@filter-change="filterChange"
@selection-change="selectionChange"
>
<!-- 循环表头数据,判断列显示类型 -->
<template v-for="col in tableHeader">
<!-- 多选框+索引 -->
<template v-if="col.type === 'selection'">
<el-table-column
class-name="table-checkbox"
:label="col.label"
:type="col.type"
:min-width="col.width"
:align="col.align"
></el-table-column>
<el-table-column
min-width="3%"
class-name="table-index"
:align="col.align"
>
<template slot-scope="scope">
{{
pageConfig.pageSize * (pageConfig.currentPage - 1) +
scope.$index +
1
}}
</template>
</el-table-column>
</template>
<!-- 索引行 -->
<el-table-column
v-else-if="col.type === 'index'"
:label="col.label"
:type="col.type"
:min-width="col.width"
:align="col.align"
>
<template slot-scope="scope">
{{
pageConfig.pageSize * (pageConfig.currentPage - 1) +
scope.$index +
1
}}
</template></el-table-column
>
<!-- 时间 -->
<el-table-column
v-else-if="col.type === 'time'"
:label="col.label"
:min-width="col.width"
:prop="col.prop"
:sortable="col.sortable"
:align="col.align"
>
<template slot-scope="scope">
<div v-if="scope.row[col.prop]">
<span class="time-con">{{ scope.row[col.prop] }}</span>
</div>
<div v-else>--</div>
</template></el-table-column
>
<!-- 操作按钮-->
<el-table-column
v-else-if="col.type === 'handle'"
:label="col.label"
:min-width="col.width"
:align="col.align"
>
<template slot-scope="scope">
<slot name="handles" :col="scope.row"></slot>
</template>
</el-table-column>
<!-- 没有具体类型的列 -->
<el-table-column
v-else
:label="col.label"
:min-width="col.width"
:prop="col.prop"
:sortable="col.sortable"
:column-key="col.columnKey"
:filters="col.filters"
:align="col.align"
>
<template slot-scope="scope">
<template v-if="!col.render">
<!-- 条件渲染 -->
<template v-if="col.formatter">
<span v-html="col.formatter(scope.row, col)"></span>
</template>
<!-- 纯文本内容 -->
<template v-else>
<span>{{ scope.row[col.prop] }}</span>
</template>
</template>
<!-- DOM元素的渲染,可绑定事件 -->
<template v-else>
<custom
:render="col.render"
:row="scope.row"
:index="scope.$index"
></custom
></template>
</template>
</el-table-column>
</template>
</el-table>
<template v-if="pageConfig.isShowPage">
<el-pagination
v-if="pageConfig.total > pageConfig.pageSize"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="pageConfig.currentPage"
:page-sizes="pageConfig.pageSizes"
:page-size="pageConfig.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageConfig.total"
class="pagination"
>
</el-pagination
></template>
</div>
</template>
<script>
import custom from './custom';
export default {
name: 'Table',
components: {},
props: {
config: {
type: Object,
default: () => {},
},
pageConfig: {
type: Object,
default: function () {
return {
isShowPage: true,
total: 20,
currentPage: 1,
pageSize: 20,
pageSizes: [20, 50, 100],
};
},
},
tableHeader: {
type: Array,
default: () => [],
},
tableData: {
type: Array,
default: () => [],
},
},
data() {
return {};
},
components: { custom },
mounted() {},
methods: {
handleSizeChange(val) {
this.$emit('sizeChange', val);
},
handleCurrentChange(val) {
this.$emit('currentChange', val);
},
sortChange(params) {
this.$emit('sortChange', params);
},
filterChange(filters) {
this.$emit('filterChange', filters);
},
selectionChange(multipleSelection) {
this.$emit('selectionChange', multipleSelection);
},
},
};
</script>
<style scoped lang="less">
</style>
其中,custom组件代码如下:
<script>
export default {
name: 'custom',
functional: true,
props: {
row: Object,
render: Function,
index: Number,
column: {
type: Object,
default: null,
},
},
render: (h, ctx) => {
const params = {
row: ctx.props.row,
index: ctx.props.index,
};
if (ctx.props.column) params.column = ctx.props.column;
return ctx.props.render(h, params);
},
};
</script>
使用方式如下:
<Table
:tableHeader="tableHeader"
:tableData="searchList"
:pageConfig="pageConfig"
@sortChange="sortChange"
@filterChange="filterChange"
@currentChange="handleCurrentChange"
@sizeChange="handleSizeChange"
@selectionChange="handleSelectionChange"
>
<template v-slot:handles="t">
<span class="btn" @click="carry(t.col)">
<template v-if="t.col.status === '未发送'"> 立即执行 </template>
<template v-else> 重新执行 </template>
</span>
<span class="btn" @click="deleteRow(t.col)"> 删除 </span>
</template>
</Table>
tableHeader数据:可以根据type类型去渲染列,formatter和render中的渲染逻辑按需修改~
tableHeader: [
{
type: 'selection', //渲染的表格行内数据类型
width: '5%', //表格列所占宽度
label: '选择', //表格列名
align: 'left', //表格列数据对其方式
},
// {
// type: 'index', //渲染的表格行内数据类型
// width: '5%', //表格列所占宽度
// label: '序号', //表格列名
// align: 'left', //表格列数据对其方式
// },
{
prop: 'planName', //字段
label: '名称', //表格列名
align: 'left', //表格列数据对其方式
width: '30%',
},
{
prop: 'taskType', //字段
label: '任务类型', //表格列名
align: 'left', //表格列数据对其方式
width: '10%',
columnKey: 'taskType',
filters: [
{
text: '已执行',
value: true,
},
{
text: '未执行',
value: false,
},
],
formatter: (row, column, cellValue, index) => {
return row.status === '成功' || row.status === '失败'
? '已执行'
: '未执行';
},
},
{
prop: 'planTime', //字段
label: '创建时间', //表格列名
align: 'left', //表格列数据对其方式
width: '15%',
sortable: 'custom',
},
{
prop: 'count', //字段
label: '显示项', //表格列名
align: 'left', //表格列数据对其方式
width: '15%',
render: (h, params) => {
if (params.row.status === '成功') {
return h('div', [
h('span', {
domProps: {
innerHTML: 2,
},
}),
]);
} else {
return h('div', [
h('span', {
// DOM 属性
domProps: {
innerHTML: '去创建',
},
//样式
style: {
color: '#f59a23',
cursor: 'pointer',
},
//绑定点击事件
on: {
click: () => {
this.goCreate(params.row);
},
},
}),
]);
}
},
},
{
type: 'handle', //类型是操作按钮
width: '15%', //表格列所占宽度
label: '操作', //表格列名
align: 'left', //表格列数据对其方式
},
],
pageConfig
pageConfig: {
isShowPage: true,
total: 0,
currentPage: 1,
pageSize: 20,
pageSizes: [5, 20, 50, 100],
},