一、问题描述:

管理搜索功能,若不在第1页进行搜索,将会搜索出n条数据但界面表格当前页数无数据。

二、原因分析:

1、当没有其他搜索条件时,切换到第2页,有数据返回。

elementUI的好看的搜索框 element表格搜索_elementui

2、然后加入搜索条件,调查询接口,由于当前页是第2页,而在该搜索条件下数据不足2页,所以该搜索条件在后台是有数据的,而当前页面无数返回。

elementUI的好看的搜索框 element表格搜索_elementUI的好看的搜索框_02

elementUI的好看的搜索框 element表格搜索_elementui_03

三、解决方案:

解决此问题,首先要先了解做表格分页搜索时,触发查询接口的时机,根据业务场景,通常分为手动触发自动触发

手动触发:

用户填写/选择搜索条件后,点击搜索触发查询,适用于搜索条件较多,且需要经常并联多个搜索条件进行查询的场景。

<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>