一、问题描述:
管理搜索功能,若不在第1页进行搜索,将会搜索出n条数据但界面表格当前页数无数据。
二、原因分析:
1、当没有其他搜索条件时,切换到第2页,有数据返回。
2、然后加入搜索条件,调查询接口,由于当前页是第2页,而在该搜索条件下数据不足2页,所以该搜索条件在后台是有数据的,而当前页面无数返回。
三、解决方案:
解决此问题,首先要先了解做表格分页搜索时,触发查询接口的时机,根据业务场景,通常分为手动触发、自动触发:
手动触发:
用户填写/选择搜索条件后,点击搜索触发查询,适用于搜索条件较多,且需要经常并联多个搜索条件进行查询的场景。
<script>
export default {
methods:{
// 查询方法
search(){
//do some search
},
// 切换分页
changeCurrentPage(val){
this.params.currentPage = val
this.search()
}
}
}
</script>
自动触发:
用户填写/选择搜索条件后,直接触发查询,适用于搜索条件较少,多使用单个搜索条件进行查询的场景。
<script>
export default {
//使用vue监听器,检测搜索条件的变化,触发查询
watch: {
params: {
handler() {
this.search()
},
deep: true, //深度检测,检测对象中每个属性的变化,耗性能
immediate: true //立即触发handler
}
}
}
</script>
问题处理:
查看el-pagination组件的文档,current-page属性是支持 .sync 修饰符的。
.sync修饰符介绍和用途see:自定义事件 — Vue.js
再查看el-pagination组件的源码,发现组件内部对于以上问题其实是有做逻辑处理的,具体每个业务页面需要结合.sync修饰符来处理这个问题:
// element-ui/packages/pagination/src/pagination.js
export default {
name: 'ElPagination',
computed: {
// 使用计算属性根据父组件传入的total或者pageCount,算出当前的页数
internalPageCount() {
if (typeof this.total === 'number') {
return Math.max(1, Math.ceil(this.total / this.internalPageSize));
} else if (typeof this.pageCount === 'number') {
return Math.max(1, this.pageCount);
}
return null;
}
},
watch: {
currentPage: {
immediate: true,
handler(val) {
this.internalCurrentPage = this.getValidCurrentPage(val);
}
},
pageSize: {
immediate: true,
handler(val) {
this.internalPageSize = isNaN(val) ? 10 : val;
}
},
// 监听器监听到当前页发生变化,会触发$emit('update:currentPage'),以修改父组件currentPage的值
// ***.sync修饰符就是在此处生效,如果没有添加.sync修饰符,$emit('update:currentPage')是修改不了父组件的currentPage值的
internalCurrentPage: {
immediate: true,
handler(newVal) {
this.$emit('update:currentPage', newVal);
this.lastEmittedPage = -1;
}
},
// 监听器监听到组件内部页数值变化,会触发以下校验
internalPageCount(newVal) {
/* istanbul ignore if */
const oldPage = this.internalCurrentPage;
if (newVal > 0 && oldPage === 0) {
this.internalCurrentPage = 1;
} else if (oldPage > newVal) { // 当页数值小于当前页,会把当前页设置为页数值,页数值为0,则把当前页设置为第1页
this.internalCurrentPage = newVal === 0 ? 1 : newVal;
this.userChangePageSize && this.emitChange();
}
this.userChangePageSize = false;
}
}
}
了解el-pagination组件的源码逻辑后,具体每个业务场景中遇到以上问题,就很容易处理了。
对于手动触发查询接口的场景:
<!-- 分页组件 -->
<el-pagination
layout="total,prev, pager, next"
background
:total="resultInfos.rowCount"
:current-page.sync="params.currentPage" //此处加上.sync修饰符
@current-change="changeCurrentPage"
/>
<script>
export default {
methods:{
//查询方法
search(){
//方式一:手动设置当前页为第一页
this.params.currentPage = 1
//do some search
},
//切换分页
changeCurrentPage(val){
this.params.currentPage = val
//this.search() //此处不再需要调查询接口,否则会导致查询接口调用两次
}
},
watch:{
//方式二:
//增加分页组件的current-page绑定值的监听,配合.sync修饰符,当前页修改都立即触发一次接口查询
'params.currentPage'(){
this.search()
}
}
}
</script>
对于自动触发查询接口的场景:
本身已经对整个查询参数对象做了深度监听,触发查询,所以只需要在el-pagination组件的current-page参数增加.sync修饰符即可。
<!-- 分页组件 -->
<el-pagination
layout="total,prev, pager, next"
background
:total="resultInfos.rowCount"
:current-page.sync="params.currentPage" //此处加上.sync修饰符
@current-change="changeCurrentPage"
/>
<script>
export default {
//使用vue监听器,检测搜索条件的变化,触发查询
watch: {
params: {
handler() {
this.search()
},
deep: true, //深度检测,检测对象中每个属性的变化,耗性能
immediate: true //立即触发handler
}
}
}
</script>