欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue自定义组件开发:使用v-model封装el-pagination组件

程序员文章站 2022-03-01 20:58:15
使用v-model绑定分页信息对象,分页信息对象包括3个核心属性参数,分页事件直接绑定查询数据的方法,消除父组件的handleSizeChange和handleCurrentChange的绑定事件方法。 ......

1、前言

  通过封装el-pagination组件开发自定义分页组件的类似文章网上已经有很多了,但看了一圈,总是不如意,于是决定还是自己动手搞一个。

2、背景

2.1、常规分页处理方法

  利用el-pagination组件的常规做法如下:

  模板部分:

        <el-pagination @size-change="handlesizechange"
            @current-change="handlecurrentchange" :current-page="pageinfo.pagenum"
            :page-sizes="[5, 10, 15, 20]" :page-size="pageinfo.pagesize"
            layout="total, sizes, prev, pager, next, jumper" :total="pageinfo.total"
            background>
        </el-pagination>

  脚本部分:

export default {
  data() {
    return {
      formdata : {
        //查询信息
        queryinfo:{
          usertype  : 0,
          deleteflag: 2,  //表示所有类型
          pagenum   : 1,
          pagesize  : 10      
        },

        // 用户类型选择框当前选中显示标签值
        usertypelabel : "所有类型",

        // 用户状态选择框当前选中显示标签值
        userstatuslabel : "所有类型"
      },
        
      // 分页信息
      pageinfo:{
        pagenum   : 1,
        pagesize  : 10,
        total     : 0
      }
    }
  },
  methods: {
    // 查询用户信息列表
    queryusers(){
      let _this = this;
      //console.log(this.pageinfo);

      this.formdata.queryinfo.pagenum = this.pageinfo.pagenum;
      this.formdata.queryinfo.pagesize = this.pageinfo.pagesize;

      this.instance.queryusers(
        this.$baseurl,this.formdata.queryinfo
      ).then(res => {
        //console.log(res.data);
        if (res.data.code == this.global.sucessrequstcode){
          //如果查询成功
          _this.pageinfo.total = res.data.data.length;
          _this.userinfolist = res.data.data;
        }else{
          alert(res.data.message);
        }
      }).catch(error => {
        alert('查询失败!');            
        console.log(error);
      });
    },    
    // 每页条数改变
    handlesizechange(newsize) {
        this.pageinfo.pagesize = newsize;
        this.queryusers();
    },
    // 当前页码改变
    handlecurrentchange(newpage) {
        this.pageinfo.pagenum = newpage;
        this.queryusers();
    }
  }

2.2、问题分析

  每个分页查询,都需要这么来一套,有点简单重复,又略有不同,即查询数据的方法会不同。

  对于有强迫症的程序猿来说,简单重复的代码无疑非常令人不爽。因此,需要将之组件化。

  分析el-pagination分页组件:

  1. 有三个核心属性参数,分别是:当前页码(current-page)、每页条数(page-size)、总记录条数(total)。核心属性参数通过绑定父组件页面数据,实行双向联动。其中当前页码和每页条数一般通过操作分页子组件来改变,总记录条数通过查询数据后由父组件进行设置。
  2. 有两个事件:分别是:@size-change(每页条数改变事件)、@current-change(当前页码改变事件)。这两个事件,分别绑定父组件的对应事件处理方法handlesizechange和handlecurrentchange,两者均调用查询数据的方法,查询数据的方法中,得到结果集后,设置总记录条数。

  自定义分页组件的开发目标:消除父组件的handlesizechange和handlecurrentchange的绑定事件方法。

  思路:使用v-model绑定分页信息对象,分页信息对象包括3个核心属性参数,即上述的pageinfo。然后分页事件直接绑定查询数据的方法。

3、方案实施

3.1、自定义分页组件

  编写一个自定义分页组件代码,文件为/src/pagination.vue。代码如下:

<template lang="html">
  <div class="pagination">
    <el-pagination 
      @size-change="handlesizechange" 
      @current-change="handlecurrentchange"
      :current-page.sync="pageinfo.pagenum"  
      :page-size="pageinfo.pagesize" 
      :page-sizes="pagesizes"
      :total="pageinfo.total"
      layout="total, sizes, prev, pager, next, jumper"
      background >
    </el-pagination>
  </div>   
</template>

<script>
  export default {
    name  : "pagination",
    model : {
        prop    : 'pageinfo',
        event   : 'change'
    },
    props : {
      // 每页条数选择项
      pagesizes: {
        type: array,
        default() {
          return [5, 10, 15, 20];
        }
      },
      // v-model绑定的数据对象
      pageinfo: {
        type: object,
        reuqired:true
      }
    },
    data(){
      return {            
      }
    },
    methods: {
      handlesizechange(newsize) {
        var newvalue={
					pagesize : newsize,
					pagenum : newsize <= this.total  ?  1  :  this.pageinfo['pagenum'] 
				};
        this.$emit('change',object.assign(this.pageinfo,newvalue));
        this.$emit('pagination');
      },
      handlecurrentchange(newpage) {
        this.$emit('change',object.assign(this.pageinfo,{pagenum : newpage}));
        this.$emit('pagination');
      }
    }    
  }
</script>

<style lang="css" scoped>
.pagination {
    padding: 10px 0;
    text-align: center;
}
</style>

  自定义分页组件,名称为pagination,其使用v-model,实现双向数据通信。当页码或每页条数改变时,触发分页事件@pagination,提供与父组件方法绑定。

  此处约定了pageinfo的字段结构如下:

      pageinfo:{
        pagenum   : 1,	//number
        pagesize  : 10,	//number
        total     : 0	//number
      }

  父组件必须提供相同结构的数据对象来绑定组件内部的pageinfo对象。

3.2、注册分页组件

  然后注册此分页组件,在main.js中加入下列代码:

import pagination  from '@/components/pagination.vue'

// 注册分页插件
vue.component('pagination', pagination)

3.3、父组件调用方法

  用pagination组件修改前面第二章的代码。

  模板部分:

        <!-- 分页区域 -->
        <pagination v-model="pageinfo" @pagination="queryusers"></pagination>

  脚本部分:

export default { 
  data() {
    return {
      formdata : {
        //查询信息
        queryinfo:{
          usertype  : 0,
          deleteflag: 2,  //表示所有类型
          pagenum   : 1,
          pagesize  : 10      
        },

        // 用户类型选择框当前选中显示标签值
        usertypelabel : "所有类型",

        // 用户状态选择框当前选中显示标签值
        userstatuslabel : "所有类型"
      },
        
      // 分页信息
      pageinfo:{
        pagenum   : 1,
        pagesize  : 10,
        total     : 0
      }
    }
  },
  methods: {
    // 查询用户信息列表
    queryusers(){
      let _this = this;
      //console.log(this.pageinfo);

      this.formdata.queryinfo.pagenum = this.pageinfo.pagenum;
      this.formdata.queryinfo.pagesize = this.pageinfo.pagesize;

      this.instance.queryusers(
        this.$baseurl,this.formdata.queryinfo
      ).then(res => {
        //console.log(res.data);
        if (res.data.code == this.global.sucessrequstcode){
          //如果查询成功
          _this.pageinfo.total = res.data.data.length;
          _this.userinfolist = res.data.data;
        }else{
          alert(res.data.message);
        }
      }).catch(error => {
        alert('查询失败!');            
        console.log(error);
      });
    }
  }

  这样,就去掉了handlesizechange和handlecurrentchange事件响应方法了。分页信息发生改变时,触发绑定的queryusers方法。

  另外,如需调整pagesizes,则在模板处类似如下设置:

:pagesizes=[10,20,30,50,100]

4、参考文章

  此组件开发主要参考了下列文章: