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 相关文章推荐
理解Javascript_08_函数对象
Oct 15 Javascript
javascript实现的使用方向键控制光标在table单元格中切换
Nov 17 Javascript
使用JavaScript进行进制转换将字符串转换为十进制
Sep 21 Javascript
javascript搜索框效果实现方法
May 14 Javascript
JavaScript中的getDay()方法使用详解
Jun 09 Javascript
使用纯JS代码判断字符串中有多少汉字的实现方法(超简单实用)
Nov 12 Javascript
基于bootstrap实现bootstrap中文网巨幕效果
May 02 Javascript
JavaScript错误处理操作实例详解
Jan 04 Javascript
JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解
Aug 16 Javascript
vue 导航内容设置选中状态样式的例子
Nov 01 Javascript
通过原生vue添加滚动加载更多功能
Nov 21 Javascript
VSCode 配置uni-app的方法
Jul 11 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
实用函数10
2007/11/08 PHP
PHP Global变量定义当前页面的全局变量实现探讨
2013/06/05 PHP
浅析php中常量,变量的作用域和生存周期
2013/08/10 PHP
用JavaScript 处理 URL 的两个函数代码
2007/08/13 Javascript
JS中字符问题(二进制/十进制/十六进制及ASCII码之间的转换)
2008/11/03 Javascript
单击按钮显示隐藏子菜单经典案例
2013/01/04 Javascript
在Javascript中 声明时用&quot;var&quot;与不用&quot;var&quot;的区别
2013/04/15 Javascript
JavaScript中this的使用详解
2013/11/08 Javascript
js获取select选中的option的text示例代码
2013/12/19 Javascript
使用jquery/js获取iframe父子级、同级获取元素的方法
2016/08/05 Javascript
vue中渐进过渡效果实现
2016/10/27 Javascript
js仿iphone秒表功能 计算平均数
2017/01/11 Javascript
JS实现复制内容到剪贴板功能
2017/02/05 Javascript
Vuejs中使用markdown服务器端渲染的示例
2017/11/22 Javascript
通过jquery.cookie.js实现记住用户名、密码登录功能
2018/06/20 jQuery
Angular设置别名alias的方法
2018/11/08 Javascript
JavaScript JMap类定义与使用方法示例
2019/01/22 Javascript
JS实现判断移动端PC端功能
2020/02/21 Javascript
在python的类中动态添加属性与生成对象
2016/09/17 Python
python实现字符串连接的三种方法及其效率、适用场景详解
2017/01/13 Python
Python操作MongoDB详解及实例
2017/05/18 Python
python将图片转base64,实现前端显示
2020/01/09 Python
你不知道的5个HTML5新功能
2016/06/28 HTML / CSS
仿CSDN Blog返回页面顶部功能实现原理及代码
2013/06/30 HTML / CSS
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
2013/11/07 HTML / CSS
Beach Bunny Swimwear官网:设计师泳装和性感比基尼
2019/03/13 全球购物
捷克建筑材料网上商店:DEK.cz
2021/03/06 全球购物
高中运动会入场词
2014/02/14 职场文书
夫妻房产协议书的格式
2014/10/11 职场文书
2015年党员创先争优承诺书
2015/01/22 职场文书
深度好文:50条没人告诉你的人生经验,句句精辟
2019/08/22 职场文书
创业计划书之个人工作室
2019/08/22 职场文书
《哪吒之魔童降世》观后感:世上哪有随随便便的成功
2019/11/08 职场文书
Java 中的 Unsafe 魔法类的作用大全
2021/06/26 Java/Android
漫画「日和酱的要求是绝对的」第3卷封面公开
2022/03/21 日漫
Spring Data JPA框架持久化存储数据到数据库
2022/04/28 Java/Android