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

  • A+
所属分类:Web前端
摘要

  通过封装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/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、参考文章

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