全球时讯:自带分页与loading的表格封装
2022-09-07 10:01:37来源:之家技术
(资料图)
首先就是新建一个组件,名字就叫做PageTable
,template
里面很简单,放上表格和分页。既然表格默认带有分页,分页的数据就放在组件内部
<script>export default { name: "PageTable", data() { return { page: { current: 1, size: 10, total: 0 }, } },}</script>
之后开始思考一个问题,就是表格的数据是从父组件传进来,还是放在组件自身。如果放在父组件里面,那么分页的变化每次都要emit
事件通知父组件,这样我们把分页和表格合在一起就失去了意义,所以表格的数据是要放在组件自身的。
表格数据放在自身,父组件就需要传进来一个获取数据的方法,就叫做fetchData
吧,在组件内部调用这个方法,就可以获取数据了。这个方法是需要知道当前分页的,并且返回数据和总条数,由此就可以定义fetchData
了
interface ResponseStructure { data: any[]; total: any;}interface fetchData { (current: number, size: number): Promise}
现在我们的组件已经变成了这个样子
<script>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 } }, }}</script>
表格一般都会带有搜索项,搜索参数等在父组件定义,并且逻辑写在fetchData
里即可,组件内部只处理通用的逻辑。父组件里点击了搜索按钮,是要触发获取事件的,父组件可以通过$refs
调用组件内部方法。目前我们定义了两个方法search
与getTableData
,点击搜索调用search
就可以了,并且会自动重置分页,如果有不想重置分页的情况,可以调用getTableData
。
目前为止,数据我们已经有了,但是并没有展示,因为element-ui的列信息(Table-column)是通过插槽的,我们使用slot
接收一下就可以了
到了这里基本逻辑已经完成了,再进一步,一般我们的表格需要loading,loading应该由父组件自己决定如何使用,但是状态的改变由本组件处理,这里可以使用.sync
修饰符,loading逻辑加在getTableData
中即可
<script>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) } }, }}</script>
loading也加完了,功能就已经完成了,但是还存在一些问题,el-table有很多的Attributes、Events和Methods,Attributes和Events我们透传给el-table即可,Methods需要el-table的ref,如果父组件直接使用ref,获取的是组件外层的div,无法获取到el-table的ref,我们暴露一个方法抛出el-table的ref即可
<script>export default { methods: { getTableRef() { return this.$refs.tableRef } }}</script>
至此,PageTable
就写完了,完整代码如下
<script>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() } }}</script>