VUE实现一个分页组件的示例


Posted in Javascript onSeptember 13, 2017

分页是WEB开发中很常用的功能,尤其是在各种前后端分离的今天,后端API返回数据,前端根据数据的count以及当前页码pageIndex来计算分页页码并渲染到页面上已经是一个很普通很常见的功能了。从最开始的jquery时代到现在的各种各样的前端框架时代,分页功能都是必不可少的。

分页大多数(基本上)情况下都是对异步数据列表的处理,这里首先需要明白一下分页的流程。

在已知每页显示数据量pageSize以及当前页码pageIndex的情况下:

  • 请求API,返回第一屏数据(pageSize内)以及所有相关条件的数据总量count
  • 将数据总量传递给page组件,来计算页码并渲染到页面上
  • 点击页码,发送请求获取该页码的数据,返回数据总量count以及该页码下的数据条目。

由于获取数据条件的变化(假设是个搜索,关键词变了),count是不定的;再或者,有个select下拉框,来控制每页显示的数据量pageSize,当它变化的时候,总页码肯定也是要变化的。因此很多情况下要重新计算页码并渲染。

了解了流程,在Vue中实现一个分页组件也就变得简单了。

简单处理,样式类似于bootstrap的分页组件,在第一页时,禁用上一页,以及首页按钮;在最后一页时,禁用下一页,以及尾页按钮;超出范围的页码以…来代替,效果图如下:

由于获取数据条件的变化(假设是个搜索,关键词变了),count是不定的;再或者,有个select下拉框,来控制每页显示的数据量pageSize,当它变化的时候,总页码肯定也是要变化的。因此很多情况下要重新计算页码并渲染。

了解了流程,在Vue中实现一个分页组件也就变得简单了。

简单处理,样式类似于bootstrap的分页组件,在第一页时,禁用上一页,以及首页按钮;在最后一页时,禁用下一页,以及尾页按钮;超出范围的页码以…来代替,效果图如下:

VUE实现一个分页组件的示例

分页组件
template

<template>
  <ul class="mo-paging">
    <!-- prev -->
    <li :class="['paging-item', 'paging-item--prev', {'paging-item--disabled' : index === 1}]" @click="prev">prev</li>
 
    <!-- first -->
    <li :class="['paging-item', 'paging-item--first', {'paging-item--disabled' : index === 1}]" @click="first">first</li>
 
    <li :class="['paging-item', 'paging-item--more']" v-if="showPrevMore">...</li>
 
    <li :class="['paging-item', {'paging-item--current' : index === pager}]" v-for="pager in pagers" @click="go(pager)">{{ pager }}</li>
 
    <li :class="['paging-item', 'paging-item--more']" v-if="showNextMore">...</li>
 
    <!-- last -->
    <li :class="['paging-item', 'paging-item--last', {'paging-item--disabled' : index === pages}]" @click="last">last</li>
 
    <!-- next -->
    <li :class="['paging-item', 'paging-item--next', {'paging-item--disabled' : index === pages}]" @click="next">next</li>
  </ul>
</template>

style(scss)

.mo-paging {
  display: inline-block;
  padding: 0;
  margin: 1rem 0;
  font-size: 0;
  list-style: none;
  user-select: none;
  > .paging-item {
    display: inline;
    font-size: 14px;
    position: relative;
    padding: 6px 12px;
    line-height: 1.42857143;
    text-decoration: none;
    border: 1px solid #ccc;
    background-color: #fff;
    margin-left: -1px;
    cursor: pointer;
    color: #0275d8;
    &:first-child {
      margin-left: 0;
    }
    &:hover {
      background-color: #f0f0f0;
      color: #0275d8;
    }
    &.paging-item--disabled,
    &.paging-item--more{
      background-color: #fff;
      color: #505050;
    }
    //禁用
    &.paging-item--disabled {
      cursor: not-allowed;
      opacity: .75;
    }
    &.paging-item--more,
    &.paging-item--current {
      cursor: default;
    }
    //选中
    &.paging-item--current {
      background-color: #0275d8;
      color:#fff;
      position: relative;
      z-index: 1;
      border-color: #0275d8;
    }
  }
}

javascript

export default {
  name : 'MoPaging',
  //通过props来接受从父组件传递过来的值
  props : {
 
    //页面中的可见页码,其他的以...替代, 必须是奇数
    perPages : { 
      type : Number,
      default : 5 
    },
 
    //当前页码
    pageIndex : {
      type : Number,
      default : 1
    },
 
    //每页显示条数
    pageSize : {
      type : Number,
      default : 10
    },
 
    //总记录数
    total : {
      type : Number,
      default : 1
    },
 
  },
  methods : {
    prev(){
      if (this.index > 1) {
        this.go(this.index - 1)
      }
    },
    next(){
      if (this.index < this.pages) {
        this.go(this.index + 1)
      }
    },
    first(){
      if (this.index !== 1) {
        this.go(1)
      }
    },
    last(){
      if (this.index != this.pages) {
        this.go(this.pages)
      }
    },
    go (page) {
      if (this.index !== page) {
        this.index = page
        //父组件通过change方法来接受当前的页码
        this.$emit('change', this.index)
      }
    }
  },
  computed : {
 
    //计算总页码
    pages(){
      return Math.ceil(this.size / this.limit)
    },
 
    //计算页码,当count等变化时自动计算
    pagers () {
      const array = []
      const perPages = this.perPages
      const pageCount = this.pages
      let current = this.index
      const _offset = (perPages - 1) / 2
 
 
      const offset = {
        start : current - _offset,
        end  : current + _offset
      }
 
      //-1, 3
      if (offset.start < 1) {
        offset.end = offset.end + (1 - offset.start)
        offset.start = 1
      }
      if (offset.end > pageCount) {
        offset.start = offset.start - (offset.end - pageCount)
        offset.end = pageCount
      }
      if (offset.start < 1) offset.start = 1
 
      this.showPrevMore = (offset.start > 1)
      this.showNextMore = (offset.end < pageCount)
 
      for (let i = offset.start; i <= offset.end; i++) {
        array.push(i)
      }
 
      return array
    }
  },
  data () {
    return {
      index : this.pageIndex, //当前页码
      limit : this.pageSize, //每页显示条数
      size : this.total || 1, //总记录数
      showPrevMore : false,
      showNextMore : false
    }
  },
  watch : {
    pageIndex(val) {
      this.index = val || 1
    },
    pageSize(val) {
      this.limit = val || 10
    },
    total(val) {
      this.size = val || 1
    }
  }
}

父组件中使用

<template>
  <div class="list">
    <template v-if="count">
      <ul>
        <li v-for="item in items">...</li>
      </ul>
      <mo-paging :page-index="currentPage" :totla="count" :page-size="pageSize" @change="pageChange">
      </mo-paging>
    </template>
  </div>
</template>
<script>
  import MoPaging from './paging'
  export default {
    //显示的声明组件
    components : {
      MoPaging 
    },
    data () {
      return {
        pageSize : 20 , //每页显示20条数据
        currentPage : 1, //当前页码
        count : 0, //总记录数
        items : []
      }
    },
    methods : {
      //获取数据
      getList () {
        //模拟
        let url = `/api/list/?pageSize=${this.pageSize}¤tPage=${this.currentPage}`
        this.$http.get(url)
        .then(({body}) => {
 
          //子组件监听到count变化会自动更新DOM
          this.count = body.count
          this.items = body.list
        })
      },
 
      //从page组件传递过来的当前page
      pageChange (page) {
        this.currentPage = page
        this.getList()
      }
    },
    mounted() {
      //请求第一页数据
      this.getList()
    } 
  }
</script>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery中$之选择器用法介绍
Apr 05 Javascript
详解JavaScript中shift()方法的使用
Jun 09 Javascript
jQuery链式调用与show知识浅析
May 11 Javascript
阻止表单提交按钮多次提交的完美解决方法
May 16 Javascript
如何利用Promises编写更优雅的JavaScript代码
May 17 Javascript
微信小程序  wx.request合法域名配置详解
Nov 23 Javascript
javascript 缓冲运动框架的实现
Sep 29 Javascript
在vue项目中,将juery设置为全局变量的方法
Sep 25 Javascript
Vue extend的基本用法(实例详解)
Dec 09 Javascript
WebPack工具运行原理及入门教程
Dec 02 Javascript
微信小程序反编译的实现
Dec 10 Javascript
jenkins自动构建发布vue项目的方法步骤
Jan 04 Vue.js
jquery 键盘事件的使用方法详解
Sep 13 #jQuery
详解angularJS+Ionic移动端图片上传的解决办法
Sep 13 #Javascript
JS解决IOS中拍照图片预览旋转90度BUG的问题
Sep 13 #Javascript
Js利用Canvas实现图片压缩功能
Sep 13 #Javascript
js 倒计时(高效率服务器时间同步)
Sep 12 #Javascript
js Date()日期函数浏览器兼容问题解决方法
Sep 12 #Javascript
JS鼠标3次点击事件实现代码及扩展思路
Sep 12 #Javascript
You might like
PHP新手上路(十四)
2006/10/09 PHP
《PHP编程最快明白》第七讲:php图片验证码与缩略图
2010/11/01 PHP
php检测图片木马多进制编程实践
2013/04/11 PHP
PHP脚本监控Nginx 502错误并自动重启php-fpm
2015/05/13 PHP
js自带函数备忘 数组
2006/12/29 Javascript
ExtJS 2.0实用简明教程 之Ext类库简介
2009/04/29 Javascript
jQuery实现炫酷的鼠标轨迹特效
2015/02/01 Javascript
jQuery实现感应鼠标动画效果自动伸长的输入框实例
2015/02/24 Javascript
javascript检测移动设备横竖屏
2016/05/21 Javascript
15款最好的Bootstrap在线编辑器
2016/08/03 Javascript
JS用斜率判断鼠标进入DIV四个方向的方法
2016/11/07 Javascript
js实现文字向上轮播功能
2017/01/13 Javascript
Bootstrap 3多级下拉菜单实例
2017/11/23 Javascript
微信小程序6位或多位验证码密码输入框功能的实现代码
2018/05/29 Javascript
如何使node也支持从url加载一个module详解
2018/06/05 Javascript
手把手带你搭建一个node cli的方法示例
2020/08/07 Javascript
js+css实现扇形导航效果
2020/08/18 Javascript
vue自定义树状结构图的实现方法
2020/10/18 Javascript
vue+echarts+datav大屏数据展示及实现中国地图省市县下钻功能
2020/11/16 Javascript
[48:31]完美世界DOTA2联赛PWL S3 DLG vs Phoenix 第二场 12.17
2020/12/19 DOTA
python使用心得之获得github代码库列表
2014/06/25 Python
在Python中marshal对象序列化的相关知识
2015/07/01 Python
Python处理JSON时的值报错及编码报错的两则解决实录
2016/06/26 Python
python django 原生sql 获取数据的例子
2019/08/14 Python
Tensorflow实现多GPU并行方式
2020/02/03 Python
一款纯css3制作的2015年元旦雪人动画特效教程
2014/12/29 HTML / CSS
CSS3中线性颜色渐变的一些实现方法
2015/07/14 HTML / CSS
HTML5的自定义属性data-*详细介绍和JS操作实例
2014/04/10 HTML / CSS
美国受欢迎的女性牛仔裤品牌:DL1961
2016/11/12 全球购物
美国最古老的精致书写工具制造商:A.T. Cross(高仕)
2018/01/30 全球购物
在阿联酋购买翻新手机和平板电脑:Teckzu
2021/02/12 全球购物
Java编程面试题
2016/04/04 面试题
如何通过jdbc调用存储过程
2012/04/19 面试题
探矿工程师自荐信
2014/01/24 职场文书
一次SQL如何查重及去重的实战记录
2022/03/13 MySQL
使用Redis实现分布式锁的方法
2022/06/16 Redis