el-pagination 分页器,当total为0时,设置pageIndex大于1,请求数据获取到总total后,分页器页码依旧展示为1

问题描述

查询表格,初始化时,pageIndex默认为1,后面因为查询条件数据缓存,pageIndex设置为了4,重新查询后,获取到了总条数 total,打印出来的数据没有问题,但是pagenation组件使用都是展示1;
el-pagination 分页器,当total为0时,设置pageIndex大于1,请求数据获取到总total后,分页器页码依旧展示为1_第1张图片

问题分析

组件外部的数据没有问题,系el-pagenation组件内部的问题;
分析:当初始化时,我们给total的默认值,设置为足够大时,分页器就可以展示正确的页码;

根本问题

el-pagenation组件内外的数据没有同步,
初始化时,当总条数为0,pageIndex大于1时,getValidCurrentPage计算出来的有效的currentPage为1,当后面根据pageIndex(大于1)、pageSize请求数据后,获取到了total,但是并没有触发,currentPage的重新计算,导致分页器始终展示1;
el-pagination 分页器,当total为0时,设置pageIndex大于1,请求数据获取到总total后,分页器页码依旧展示为1_第2张图片

问题解决

当总条数发生变化时,手动触发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>

你可能感兴趣的:(vue.js,前端,javascript)