zoukankan      html  css  js  c++  java
  • Vue自定义组件开发:使用v-model封装el-pagination组件

    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/componets/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、参考文章

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

    作者:阿拉伯1999
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
    养成良好习惯,好文章随手顶一下。
  • 相关阅读:
    深入Android 【一】 —— 序及开篇
    Android中ContentProvider和ContentResolver使用入门
    深入Android 【六】 —— 界面构造
    The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the ser
    Dynamic Business代码片段总结
    对文件的BuildAction以content,resource两种方式的读取
    paraview 3.12.0 windows下编译成功 小记
    百度网盘PanDownload使用Aria2满速下载
    netdata的安装与使用
    用PS给证件照排版教程
  • 原文地址:https://www.cnblogs.com/alabo1999/p/14979800.html
Copyright © 2011-2022 走看看