问题描述
查询表格,初始化时,pageIndex默认为1,后面因为查询条件数据缓存,pageIndex设置为了4,重新查询后,获取到了总条数 total,打印出来的数据没有问题,但是pagenation组件使用都是展示1;
问题分析
组件外部的数据没有问题,系el-pagenation组件内部的问题;
分析:当初始化时,我们给total的默认值,设置为足够大时,分页器就可以展示正确的页码;
根本问题
el-pagenation组件内外的数据没有同步,
初始化时,当总条数为0,pageIndex大于1时,getValidCurrentPage计算出来的有效的currentPage为1,当后面根据pageIndex(大于1)、pageSize请求数据后,获取到了total,但是并没有触发,currentPage的重新计算,导致分页器始终展示1;
问题解决
当总条数发生变化时,手动触发handleCurrentChange内部事件(用户修改页码时会触发的事件),重置el-pagenation组件内的internalCurrentPage数据
@Watch('total')
onPageIndexChange() {
this.$nextTick(() => {
//* 当总条数发生变化时,重置el-pagenation组件内的internalCurrentPage数据
const basePagenationRef: any = this.$refs.basePagenation;
basePagenationRef.handleCurrentChange(this.formData.pageIndex)
})
}
缺点:这种解决方案,相当于用户手动修改了页码,会导致组件内部再次抛出current-change事件,bug体现在,导致接口请求了两次,可以判断一下,如果是totalChange触发抛出的current-change,不继续向外部抛出change事件;详细代码如下
附上BasePagenation.vue组件代码
<template>
<el-pagination
ref="basePagenation"
class="com_pagenation"
:disabled="loading"
@size-change="sizeOnChange"
@current-change="currentOnChange"
:page-sizes="pageSizes"
:current-page.sync="formData.pageIndex"
:page-size.sync="formData.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
v-bind="$attrs"
>
</el-pagination>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch, } from 'vue-property-decorator'
@Component({
name: 'BasePagenation',
})
export default class extends Vue {
@Prop({ default: () => ({pageIndex: 1, pageSize: 10, }) }) formData!: any; //? 分页时,默认的分页页码,分页大小
@Prop({ default: 0 }) total!: number; //? 分页时的总条数
@Prop({ default: () => [10, 20, 50, 100, 300] }) pageSizes?: number[]; //? 分页器的每页显示个数选择器的选项设置
@Prop({ default: false }) loading!: boolean; //? 请求时,展示加载中
//* 事件监听
//* change //? 分页页码、分页页数改变时触发的事件监听
noNeedEmitChange: boolean = false;
@Watch('total')
onPageIndexChange() {
this.$nextTick(() => {
this.noNeedEmitChange = true;
//* 当总条数发生变化时,重置el-pagenation组件内的internalCurrentPage数据
const basePagenationRef: any = this.$refs.basePagenation;
basePagenationRef.handleCurrentChange(this.formData.pageIndex)
basePagenationRef.internalPageSize
})
}
sizeOnChange(val) {
if (this.noNeedEmitChange) { //* 不需要抛出事件
this.noNeedEmitChange = false;
return;
}
this.$emit('change', 'size', val);
}
currentOnChange(val) {
if (this.noNeedEmitChange) { //* 不需要抛出事件
this.noNeedEmitChange = false;
return;
}
this.$emit('change', 'page', val);
}
}
</script>
<style lang="scss" scoped>
.com_pagenation {
// UI调整,以下样式注释
// text-align: right;
// margin-right: 40px;
// padding-top: 10px;
// ! 以下样式是UI调整下分页器的新样式
// 字体14px
$pagination-font-size: 14px;
// 分页器内各部分高度32px
$pagination-content-height: 32px;
width: 100%;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
font-size: $pagination-font-size;
::v-deep {
// 总页数样式
.el-pagination__total {
font-size: $pagination-font-size;
}
// 快捷跳转样式
.el-pagination__jump {
font-size: $pagination-font-size;
height: $pagination-content-height;
}
// 页容量样式
.el-pagination__sizes {
height: $pagination-content-height;
}
// 输入框的样式
input {
height: $pagination-content-height !important;
// 页容量和快捷跳转内的字体大小
font-size: $pagination-font-size !important;
border-radius: 6px !important;
}
// 页码样式
li.number {
font-size: $pagination-font-size;
font-weight: normal;
min-width: $pagination-content-height;
height: $pagination-content-height;
line-height: $pagination-content-height;
border-radius: 6px;
&.active {
color: #6D55FF;
background-color: #F6F7FF;
font-weight: 600;
}
}
li.number:not(:first-of-type) {
margin-left: 8px;
}
}
}
</style>