基于el-table表格与el-pagination分页二次封装
#el-table封装
<template>
<div>
<el-table
class="customer"
border
size="mini"
:data="tableData"
@selection-change="handleSelectionChange"
ref="Dynamic-Table"
style="width: 100%"
>
<!-- <el-table-column label="序号" align="center" type="index" /> -->
<!-- 循环表头数据,判断列显示类型 -->
<template v-for="(col, index) in tableHeader">
<!-- 索引行 -->
<el-table-column
v-if="col.type == 'index'"
:label="col.label"
:key="index"
:type="col.type"
:width="col.width"
:align="col.align"
:fixed="col.fixed"
/>
<!-- 自定义表头 -->
<el-table-column
:key="index"
v-else-if="col.type == 'header'"
:width="col.width"
:align="col.align"
>
<template slot="header">
<el-input
v-model="col.prop"
size="mini"
placeholder="输入列"
class="input_text_center"
/>
</template>
<template slot-scope="scope">
<slot :row="scope.row" :col="col"></slot>
</template>
</el-table-column>
<!-- 多选框 -->
<el-table-column
v-else-if="col.type == 'selection'"
:key="index"
:type="col.type"
:width="col.width"
:align="col.align"
:fixed="col.fixed"
></el-table-column>
<!-- 输入框 -->
<el-table-column
v-else-if="col.type == 'input'"
:key="index"
:label="col.label"
:width="col.width"
:align="col.align"
:prop="col.prop"
>
<template slot-scope="scope">
<el-input v-model="scope.row[col.prop]" class="input_text_center" />
</template>
</el-table-column>
<!-- 图片 -->
<el-table-column
v-else-if="col.type == 'image'"
:key="index"
:label="col.label"
:width="col.width"
:prop="col.prop"
>
<template slot-scope="scope">
<div class="content-image"><img :src="scope.row[col.prop]" /></div>
</template>
</el-table-column>
<!-- 给日期行加个好看的icon,属于自定义,所以要单独抽离出来 -->
<el-table-column
v-else-if="col.type == 'date'"
:key="index"
:label="col.label"
:width="col.width"
:min-prop="col.prop"
>
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row[col.prop] }}</span>
</template>
</el-table-column>
<!-- 操作按钮,我们不知道表格操作按钮业务需求是什么样子的,那我们就给插槽,不同业务可以按需求添加操作按钮 -->
<el-table-column
v-else-if="col.type == 'handle'"
:key="index"
:label="col.label"
:min-width="col.width"
:align="col.align"
:fixed="col.fixed"
>
<template slot-scope="scope">
<slot :name="col.name" :row="scope.row" :col="col"></slot>
</template>
</el-table-column>
<!-- 自由项 -->
<slot v-else-if="$scopedSlots[col.name]" :name="col.name" :column="col"></slot>
<!-- 对于其他没有类型的列,统统算作普通默认类型。直接按照表格属性呈现就行 -->
<el-table-column
v-else
:label="col.label"
:key="index"
:min-width="col.width"
:prop="col.prop"
:align="col.align"
:fixed="col.fixed"
></el-table-column>
</template>
</el-table>
<Pagination
class="mt10"
v-if="config !== undefined && config.total > 0"
:total="config.total"
v-on="$listeners"
:page.sync="config.searchList.page"
:entry.sync="config.searchList.pageSize"
:pageSizes.sync="config.searchList.pageSizes"
/>
</div>
</template>
<script>
// type:{
// selection: checkbox选项,
// date: 日期格式,
// button: 操作按钮,
// image: 图片,
// index: 索引,
// expand: 列表展开,
// tag: 一般用于筛选类型标签,
// }
import Pagination from './Pagination';
export default {
components: { Pagination },
name: 'DynamicTable',
props: {
config: {
type: Object,
default: () => {},
},
tableHeader: {
type: Array,
default: () => [],
},
tableData: {
type: Array,
default: () => [],
},
},
data() {
return {
tRef: null,
};
},
created() {
this._initial();
},
methods: {
_initial() {
this.$nextTick(() => {
this.tRef = this.$refs['Dynamic-Table'];
// this._extendTableAttrs(this.tRef)
this._extendTableMethods(this.tRef);
});
},
// 继承el-table的方法
_extendTableMethods(ref) {
const TABLE_METHODS = [
'selection',
'clearSelection',
'toggleRowSelection',
'toggleAllSelection',
'doLayout',
'sort',
];
const methodMap = {};
TABLE_METHODS.forEach(method => {
methodMap[method] = ref[method];
});
Object.assign(this, methodMap);
},
handleSelectionChange(selection) {
this.$emit('selection-change', selection);
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .input_text_center {
.el-input__inner {
text-align: center;
}
}
</style>
#分页
<template>
<div class="pagination">
<el-pagination
background
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:layout="layout"
:page-sizes="pageSizes"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script>
export default {
name: 'Pagination',
props: {
total: {
required: true,
type: Number,
}, //数据总数
page: {
type: Number,
default: 1,
}, //当前页数
entry: {
type: Number,
default: 5,
}, //每页显示条目个数
pageSizes: {
type: Array,
default() {
return [5, 10, 20, 30, 50];
},
}, //设置一次展示多少行数据
layout: {
type: String,
default: 'total, sizes, prev, pager, next, jumper',
}, //分页的构成,例如是否添加上一页下一页,是否支持输入跳转
},
computed: {
currentPage: {
get() {
return this.page;
},
set(val) {
this.$emit('update:page', val);
},
}, //利用计算属性来重置普攻。让我们可以改变父组件传递过来的分页页数和条目
pageSize: {
get() {
return this.entry;
},
set(val) {
this.$emit('update:entry', val);
},
},
},
methods: {
//改变分页页数和条目,通知父组件做相应的数据改变
handleCurrentChange(val) {
this.$emit('handleCurrentChange', { page: this.currentPage, entry: val });
},
handleSizeChange(val) {
this.$emit('handleSizeChange', { page: this.pageSize, entry: val });
},
},
};
</script>
#使用
<DynamicTable
v-loading="loading" //这些可加可不加
@handleCurrentChange="handleCurrentChange"
@handleSizeChange="handleSizeChange"
element-loading-text="加载中..." //这些可加可不加
element-loading-spinner="el-icon-loading" //这些可加可不加
:tableData="tableData"
:tableHeader="tableHeader"
:config="config"
/>
data(){
/**
tableHeader: [
{
type: 'index',
width: '55',
label: '序号',
align: 'center',
},
{
prop: '',
width: '120',
label: '',
align: 'center',
},
{
name:"name",
//如有操作列必需要有name值name值自定义,使用插槽方式
<template v-slot:name="{row,index}">
<el-button size="mini" type="danger" >操作</el-button>
</template>
type:"handle",
label:"操作"
width: '120',
align: 'center',
}
],
*/
return {
tableHeader: [], //空数组是因为我们是动态渲染表头写死的话参照上面注释
config: {
total: 0,
searchList: {
pageSizes: pageSizeOptions,
page: 1,
pageSize: 10,
},
},
tableData: [],
}
},
methods:{
handleCurrentChange(val) {
this.config.searchList.page = val.entry;
this.表格请求数据();
},
handleSizeChange(val) {
this.config.searchList.pageSize = val.entry;
this.表格请求数据();
},
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义