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 相关文章推荐
JS合并数组的几种方法及优劣比较
Sep 19 Javascript
使用mini-define实现前端代码的模块化管理
Dec 25 Javascript
jquery插件bxslider用法实例分析
Apr 16 Javascript
js实现拖拽效果(构造函数)
Dec 14 Javascript
使用jQuery Rotare实现微信大转盘抽奖功能
Jun 20 Javascript
vue项目中导入swiper插件的方法
Jan 30 Javascript
使用selenium抓取淘宝的商品信息实例
Feb 06 Javascript
vue项目中jsonp跨域获取qq音乐首页推荐问题
May 30 Javascript
JavaScript实现多张图片放大镜效果示例【不限定图片尺寸,rem单位】
May 14 Javascript
Vue 用Vant实现时间选择器的示例代码
Oct 25 Javascript
Vue快速实现通用表单验证的示例代码
Jan 09 Javascript
js用正则表达式筛选年月日的实例方法
Jan 04 Javascript
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
常用星际术语索引(新手指南)
2020/03/04 星际争霸
PHP序列号生成函数和字符串替换函数代码
2012/06/07 PHP
php车辆违章查询数据示例
2016/10/14 PHP
php中__toString()方法用法示例
2016/12/07 PHP
你的编程语言可以这样做吗?
2006/09/07 Javascript
Chrome中模态对话框showModalDialog返回值问题的解决方法
2010/05/25 Javascript
javascript setAttribute, getAttribute 在不同浏览器上的不同表现
2010/08/05 Javascript
关于extjs4如何获取grid修改后的数据的问题
2013/08/07 Javascript
JS实现黑客帝国文字下落效果
2015/09/01 Javascript
AngularJs表单验证实例详解
2016/05/30 Javascript
JS实现环形进度条(从0到100%)效果
2016/07/05 Javascript
node.js express安装及示例网站搭建方法(分享)
2016/08/22 Javascript
JavaScript常用正则验证函数实例小结【年龄,数字,Email,手机,URL,日期等】
2017/01/23 Javascript
angular4 JavaScript内存溢出问题
2018/03/06 Javascript
Vue 父子组件数据传递的四种方式( inheritAttrs + $attrs + $listeners)
2018/05/04 Javascript
使用JavaScript实现网页秒表功能(含开始、暂停、继续、重置功能)
2020/06/05 Javascript
微信小程序选择图片控件
2021/01/19 Javascript
python类装饰器用法实例
2015/06/04 Python
python 自动化将markdown文件转成html文件的方法
2016/09/23 Python
Python实现将SQLite中的数据直接输出为CVS的方法示例
2017/07/13 Python
解决Django删除migrations文件夹中的文件后出现的异常问题
2019/08/31 Python
python基于opencv检测程序运行效率
2019/12/28 Python
python实现ip地址的包含关系判断
2020/02/07 Python
python中scrapy处理项目数据的实例分析
2020/11/22 Python
HTML5中新标签和常用标签详解
2014/03/07 HTML / CSS
马来西亚户外装备商店:PTT Outdoor
2019/07/13 全球购物
助人为乐道德模范事迹材料
2014/08/16 职场文书
单位在职证明书
2014/09/11 职场文书
医院护士见习期自我鉴定
2014/09/15 职场文书
刑事辩护授权委托书范本
2014/10/17 职场文书
5.12护士节活动总结
2015/02/10 职场文书
投诉书范文
2015/07/02 职场文书
军事理论课感想
2015/08/11 职场文书
实体类或对象序列化时,忽略为空属性的操作
2021/06/30 Java/Android
梳理总结Python开发中需要摒弃的18个坏习惯
2022/01/22 Python
Python docx库删除复制paragraph及行高设置图片插入示例
2022/07/23 Python