1.描述:
使用element pagination组件时,如果你的currentPage在靠后的页数,这时改变pageSize,那么可能导致size-change和current-change事件同时被触发,如果你的数据请求直接或间接使用这两个事件回调进行,且没有进行任何处理,那么自然便会发送两次网络请求。
2.代码解决:
我只需要一个分页事件,因此没有直接使用size-change和current-change,而是集中放在了一个自定义事件pagination里。但是其他场景思路也是完全一样的。
以下是伪代码:
<template>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-size="pageSize"
:total="total"
:page-sizes="[10, 20, 30, 50, 200, 1000, 2000]"
layout="total, sizes, prev, pager, next, jumper"
background
>
</template>
<script>
data() {
return {
//把currentPage、pageSize保存在pagination对象里
pagination: {
currentPage: this.currentPage,
pageSize: this.pageSize,
}
};
},
props: {
currentPage: String,
pageSize: String
}
watch: {
pagination: {
handler({currentPage, pageSize}) {
//如果当前页超出最大页数,则不emit事件
let maxPage = Math.ceil(this.total / pageSize)
if (currentPage > maxPage) return
this.$emit('pagination', {currentPage, pageSize})
},
deep: true
}
},
methods: {
handleSizeChange(pageSize) {
this.pagination.pageSize = pageSize
this.$emit("sizeChange", pageSize);
},
handleCurrentChange(currentPage) {
this.pagination.currentPage = currentPage
this.$emit("currentChange", currentPage);
},
}
</script>
3.分析:
这个问题本不应该存在的,其他组件库都是把分页事件放在一个pagination事件里,这不是什么难事,如果你了解pagination组件封装的话。比如quasar自带的组件库、antd:
element却没有一个这样的事件,且分出size-change和current-change这两个事件来也没有太大意义,因为这两个事件不会比一个pagination事件能多干什么事情。但这也不是什么大问题。
出现这个问题,是因为改变了pageSize,最大页数(下面叫maxPage)也会改变。
这分两种情况,一种是pageSize变小,这显然不会有什么坏的影响,element对于这种情况做的是保持currentPage不变。
另一种情况,是pageSize变大,即maxPage变小,这时如果currentPage没有超出maxPage,那么element对于这种情况做的是也是保持currentPage不变。但是如果currentPage超出了maxPage,那么element就会把maxPage赋值给currentPage,同时size-change和current-change这两个事件都会触发。
所以你最好不要在size-change和current-change这两个事件的回调里都发请求,而是封装一下,只$emit一个类似于“pagination”这样的event。
现在的问题在于,如何在出现pageSize变大这种情况下,利用size-change和current-change这两个事件,拿到currentPage、pageSize,但只emit一次pagination event。
关键在于,改变pageSize,maxPage也随之改变了,所以需要判断是否要改变currentPage,因为可能出现currentPage大于maxPage的情况,这是不对的,所以只需要判断下if (currentPage > maxPage) return即可