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加ASP二级域名转向的代码
May 17 Javascript
原创jQuery弹出层插件分享
Apr 02 Javascript
举例详解JavaScript中Promise的使用
Jun 24 Javascript
JavaScript实现横向滑出的多级菜单效果
Oct 09 Javascript
Javascript实现单例模式
Jan 24 Javascript
Document.body.scrollTop的值总为零的快速解决办法
Jun 09 Javascript
简单的js表格操作
Sep 24 Javascript
js鼠标按键事件和键盘按键事件用法实例汇总
Oct 03 Javascript
JS中移除非数字最多保留一位小数
May 09 Javascript
vue引入axios同源跨域问题
Sep 27 Javascript
JS中间件设计模式的深入探讨与实例分析
Apr 11 Javascript
js实现鼠标拖曳效果
Dec 30 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
农民C键的运用技巧
2020/03/04 星际争霸
php数据结构与算法(PHP描述) 查找与二分法查找
2012/06/21 PHP
一组PHP加密解密函数分享
2014/06/05 PHP
PHP使用strtotime获取上个月、下个月、本月的日期
2015/12/30 PHP
PHP Curl模拟登录微信公众平台、新浪微博实例代码
2016/01/28 PHP
PHP6连接SQLServer2005的三部曲
2016/04/15 PHP
CodeIgniter集成smarty的方法详解
2016/05/26 PHP
PHP实现可添加水印与生成缩略图的图片处理工具类
2018/01/16 PHP
JQuery 学习笔记01 JQuery初接触
2010/05/06 Javascript
jQuery UI Autocomplete 1.8.16 中文输入修正代码
2012/04/16 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
如何获取select下拉框的值(option没有及有value属性)
2013/11/08 Javascript
js使用for循环与innerHTML获取选中tr下td值
2014/09/26 Javascript
javascript手工制作悬浮菜单
2015/02/12 Javascript
javascript创建动态表单的方法
2015/07/25 Javascript
BootStrap 图标icon符号图标glyphicons不正常显示的快速解决办法
2016/12/08 Javascript
实例详解Vue项目使用eslint + prettier规范代码风格
2018/08/20 Javascript
Nodejs异步流程框架async的方法
2019/06/07 NodeJs
JavaScript 截取字符串代码实例
2019/09/05 Javascript
python base64 decode incorrect padding错误解决方法
2015/01/08 Python
Python实现把数字转换成中文
2015/06/29 Python
使用Python实现跳一跳自动跳跃功能
2019/07/10 Python
Python中的类与类型示例详解
2019/07/10 Python
python实现简单聊天室功能 可以私聊
2019/07/12 Python
python实现日志按天分割
2019/07/22 Python
基于Python的OCR实现示例
2020/04/03 Python
Python函数必须先定义,后调用说明(函数调用函数例外)
2020/06/02 Python
你可能不熟练的十个前端HTML5经典面试题
2018/07/03 HTML / CSS
LightInTheBox法国站:中国跨境电商
2020/03/05 全球购物
2014年移动公司工作总结
2014/12/08 职场文书
敬老院活动感想
2015/08/07 职场文书
校园安全主题班会
2015/08/12 职场文书
高效笔记技巧分享:学会这些让你不再困扰
2019/09/04 职场文书
Python机器学习算法之决策树算法的实现与优缺点
2021/05/13 Python
业余无线电通联Q语
2022/02/18 无线电
Ubuntu18.04下QT开发Android无法连接设备问题解决实现
2022/06/01 Java/Android