首先就是自带新建一个组件,名字就叫做PageTable,分页封装template里面很简单,表格放上表格和分页。自带既然表格默认带有分页,分页封装分页的表格数据就放在组件内部 layout="total, sizes, prev, pager, next, jumper" :current-page.sync="page.current" :page-size.sync="page.size" :total="page.total" /> export default { name: PageTable, data() { return { page: { current: 1, size: 10, total: 0 }, } }, } 之后开始思考一个问题,就是自带表格的数据是从父组件传进来,还是分页封装放在组件自身。如果放在父组件里面,表格那么分页的自带变化每次都要emit事件通知父组件,这样我们把分页和表格合在一起就失去了意义,分页封装所以表格的表格数据是要放在组件自身的。 表格数据放在自身,自带父组件就需要传进来一个获取数据的分页封装方法,就叫做fetchData吧,表格在组件内部调用这个方法,就可以获取数据了。这个方法是需要知道当前分页的,并且返回数据和总条数,云服务器提供商由此就可以定义fetchData了 interface ResponseStructure { data: any[]; total: any; } interface fetchData { (current: number, size: number): Promise 现在我们的组件已经变成了这个样子 layout="total, sizes, prev, pager, next, jumper" :current-page.sync="page.current" :page-size.sync="page.size" :total="page.total" @size-change="search" @current-change="getTableData" /> export default { name: PageTable, props: { fetchData: { type: Function, required: true }, }, data() { return { page: { current: 1, size: 10, total: 0 }, tableData: [] } }, methods: { search() { this.page.current = 1 this.getTableData() }, async getTableData() { try { const { current, size } = this.page const { data, total } = await this.fetchData(current, size) this.tableData = data this.page.total = total } catch (err) { this.tableData = [] this.page.total = 0 } }, } } 表格一般都会带有搜索项,搜索参数等在父组件定义,并且逻辑写在fetchData里即可,组件内部只处理通用的逻辑。父组件里点击了搜索按钮,是要触发获取事件的,父组件可以通过$refs调用组件内部方法。目前我们定义了两个方法search与getTableData,点击搜索调用search就可以了,并且会自动重置分页,如果有不想重置分页的情况,可以调用getTableData。 目前为止,数据我们已经有了,但是并没有展示,因为element-ui的列信息(Table-column)是通过插槽的,我们使用slot接收一下就可以了 到了这里基本逻辑已经完成了,再进一步,一般我们的表格需要loading,loading应该由父组件自己决定如何使用,但是云服务器状态的改变由本组件处理,这里可以使用.sync修饰符,loading逻辑加在 getTableData中即可 export default { props: { loading: { type: Boolean, default: false, }, }, methods: { async getTableData() { try { const { current, size } = this.page this.$emit(update:loading, true) const { data, total } = await this.fetchData(current, size) this.tableData = data this.page.total = total } catch (err) { this.tableData = [] this.page.total = 0 } finally { this.$emit(update:loading, false) } }, } } loading也加完了,功能就已经完成了,但是还存在一些问题,el-table有很多的Attributes、Events和Methods,Attributes和Events我们透传给el-table即可,Methods需要el-table的ref,如果父组件直接使用ref,获取的是组件外层的div,无法获取到el-table的ref,我们暴露一个方法抛出el-table的ref即可 export default { methods: { getTableRef() { return this.$refs.tableRef } } } 至此,PageTable就写完了,完整代码如下 v-bind="$attrs" v-on="$listeners" ref="tableRef" :data="tableData" @sort-change="sortChange" > layout="total, sizes,prev, pager, next, jumper" :current-page.sync="page.current" :page-sizes="pageSizes" :page-size.sync="page.size" :total="page.total" @size-change="search" @current-change="getTableData" /> export default { name: PageTable, props: { / * 获取表格数据的请求方法 * @param { Number} current 当前页数 * @param { Number} size 每页条数 * @param { Object} sort 排序 * @param { String} sort.orderBy 排序的key * @param { (ascending|descending|null)} sort.rule 排序的规则 */ fetchData: { type: Function, required: true }, pageSizes: { type: Array, default: () => [ 10, 20, 50, 100, 150 ] }, loading: { type: Boolean, default: false }, }, data() { return { page: { current: 1, size: 10, total: 0 }, tableData: [], sort: { orderBy: , rule: } } }, created() { this.getTableData() }, methods: { /** 搜索,可通过 $refs 调用此方法 */ search() { this.page.current = 1 this.getTableData() }, /** 获取表格数据,可通过 $refs 调用此方法 */ async getTableData() { try { const { current, size } = this.page this.$emit(beforeFetch) this.$emit(update:loading, true) const { data, total } = await this.fetchData(current, size, this.sort) this.$emit(fetched, data) this.tableData = data this.page.total = total } catch (err) { this.$emit(fetched, []) this.tableData = [] this.page.total = 0 } finally { this.$emit(update:loading, false) } }, /** 获取el-table的ref,可通过 $refs 调用此方法 */ getTableRef() { return this.$refs.tableRef }, sortChange({ prop, order }) { this.sort = { orderBy: prop, rule: order || } this.getTableData() } } }