vue封装的分页

https://juejin.im/entry/58f85550b123db00623587bf

使用 vue2.0 实现一个简洁的分页组件

阅读 2455

收藏 94

2017-04-20

原文链接:segmentfault.com

0元快速上手小程序开发?还是腾讯官方授课?ke.qq.com

前言

  1. 使用 vue-cli 初始化项目
  1. 使用 vuex 管理数据
  1. node v6.9.2,npm v3.10.9
  • 分页效果预览:
    demo

[图片上传失败...(image-5aaaf1-1547692269209)]

分页原理

  • 实现分页主要依靠两个参数,偏移量(offset)、限制数(limit)。点击分页发送 Ajax 请求,将这两个参数传给后端,后端从数据库筛选出对应的数据返回给前端,前端将获取到的数据添加到页面中,分页组件根据偏移量和限制数显示对应的页码,这是一个简单地实现分页的思路。

分页类型

  • 分页一般分为两种类型,一种经常用于移动端的滚动加载,或是一个按钮点击即可加载更多。这种分页实现起来比较简单,前端仅需定义一个 offset 变量,每次 ajax 请求时 offset += limit,然后将获取到的内容 append 上去即可。

  • 另一种是显示总页数、当前页数、上一页、下一页按钮,且页数较多时将中间页数用省略号表示。这种分页实现起来稍微复杂一点,但用户体验更好,本文讨论的就是如何使用 vue 实现这样的分页组件。

分页组件

  • 创建 pagination.vue 文件。

    <template>
        <div class="page-wrap">
          <ul v-show="prePage" class="li-page" v-tap="{methods: goPrePage}">上一页</ul>
          <ul>
            <li v-for="i in showPageBtn" :class="{active: i === currentPage, pointer: i, hover: i && i !== currentPage}"
                v-tap="{methods: goPage, i: i}">
              <a v-if="i" class="notPointer">{{i}}</a>
              <a v-else>···</a>
            </li>
          </ul>
          <ul v-show="nextPage" class="li-page" v-tap="{methods: goNextPage}">下一页</ul>
        </div>
    
    </template>
    
  • 组件的作用域是独立的,父组件通信通过 props 向其传递数据,分页组件通过 $emit 触发在父组件定义的事件实现和父组件的通信,因此预设从父组件获取到需显示的总数 num 为 30 , limit 为 5,当然你也可以随意设置这两个值~

    let that
    export default{
        data(){
          that = this
          return{
            num: 30,
            limit: 5
          }
        }
    }
    
  • 计算几个变量,在这里可以使用 vue 的计算属性 computed

    • 总页数 totalPage 应该等于需显示的总数除以每页显示的个数,并向上取整,这个很好理解。
        computed: {
          totalPage() {
            return Math.ceil(that.num / that.limit)
          }
        }
    
    • 偏移量 offset,因为点击上下页、制定页码均会改变 offset 变量,父组件也需要用到这个变量发送 ajax 请求,因此使用 vuex 存储 offset。
        // pagination.vue
        computed: {
          offset() {
              return that.$store.state.offset
          }
        }
    
    • 当前页面 currentPage,当前页面是比较重要的一个变量,显示用户当前所处页数,已知偏移量和每页显示数量可以得出当前页面是二者的余数向上取整,因为页数不从0开始,因此
        computed: {
          currentPage() {
            return Math.ceil(that.offset / that.limit) + 1
          }
        }
    
    • 是否显示上一页按钮 prePage,因为在首页的时候偏移量为0,因此只要偏移量不等于0则当前页面肯定不在第一页,则显示上一页按钮,并且 num 不等于 0。
        coumputed: {
          prePage() {
            return that.offset !== 0 && that.num
          }
        }
    
    • 是否显示下一页按钮 nextPage,这个也很好理解,只要偏移量和每页显示的个数相加小于需显示的总数,则显示下一页按钮,并且 num 不等于 0。
        computed: {
          nextPage() {
            return (that.offset + that.limit < that.num) && that.num
          }
        }
    
    • 页码计算 showPageBtn,页码计算是这个分页组件的核心内容,基本思路是当总页数不大于5时,显示全部页码;当总页数大于5时,始终显示首尾页码,当当前页码距首页小于2时,显示前三页页码和省略号;当当前页码距尾页小于2时,显示后三页页码,当当前页码距首页等于2时,显示前四页页码和省略号;当当前页码距尾页等于2时,显示后四页页码和省略号;当当前页码距首页大于3且距尾页大于3时,显示当前页码和当前页码的前一页和后一页,两边各有一个省略号;在这里我们使用0代表省略号
        computed: {
          showPageBtn() {
              let pageNum = that.totalPage,
                  index = that.currentPage,
                  arr = []
              if (pageNum <= 5) {
                for(let i = 1; i <= pageNum; i++) {
                  arr.push(i)
                }
                return arr
              }
              if (index <= 2) return [1,2,3,0,pageNum]
              if (index >= pageNum -1) return [1,0, pageNum -2, pageNum -1, pageNum]
              if (index === 3) return [1,2,3,4,0,pageNum]
              if (index === pageNum -2) return [1,0, pageNum-3, pageNum-2, pageNum-1, pageNum]
              return [1,0, index-1, index, index + 1, 0, pageNum]
            }
        }
    
  • 跳转事件,分别点击上一页、下一页和指定页码。

    methods: {
      goPage(params) {
        if (params.i === 0 || params.i === that.currentPage) return
        that.$store.commit('GO_PAGE', (params.i-1) * that.limit)
        that.$emit('getNew')
      },
      goPrePage() {
        that.$store.commit('PRE_PAGE', that.limit)
        that.$emit('getNew')
      },
      goNextPage() {
        that.$store.commit('NEXT_PAGE', that.limit)
        that.$emit('getNew')
      }
    }

vuex 部分

  • 在此介绍一下 vuex 部分的实现,学习了二哲大大的 vuex 部分的结构。在 src 目录下(和 components 目录平级),新建 store 目录,其中 index.js 文件传入 mutation,初始化 vuex;

    // vuex store/index.js
    import Vue from 'vue'
    import Vuex from 'vuex'
    import mutations from './mutations'
    
    Vue.use(Vuex);
    
    const state = {
    offset: 0
    };
    
    export default new Vuex.Store({
    state,
    mutations
    })
    
  • mutation-types.js 记录所有的事件名,其实这个文件最大的好处是能让我们更直观地管理所有的 vuex 方法,它的优点会在项目复杂后凸显出来,项目复杂时我们可能会使用 vuex 存储很多数据、定义很多方法,这时 mutation-types.js 就能更好更直观地管理这些方法。这也是一种设计理念嘛,有利于后期维护。

    // mutation-types.js
    export const PRE_PAGE = 'PRE_PAGE'
    export const NEXT_PAGE = 'NEXT_PAGE'
    export const GO_PAGE = 'GO_PAGE'
    
  • mutation.js 这是 vuex 的核心文件,注册了实现的所有事件,我们定义了点击上一页、下一页和跳转到指定页面的方法。

    // mutation.js
    import * as types from './mutation-types'
    
    export default {
    // 分页 上一页
    [types.PRE_PAGE] (state, offset) {
      state.offset -= offset
    },
    // 分页 下一页
    [types.NEXT_PAGE] (state, offset) {
      state.offset += offset
    },
    // 分页 跳转到指定页码
    [types.GO_PAGE] (state, offset) {
      state.offset = offset
    }
    };
    

how to run

$ npm install 

$ npm run dev

// 访问 http://localhost:8088/index.html
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容

  • (以下使用ssm+jsp实现显示所有电影为例子) 1.封装一个PageBean类 package com.enti...
    何文杰啊阅读 3,777评论 0 0
  • 在实际的项目开发中,常常需要使用到分页,分页方式分为两种:前端分页和后端分页。 前端分页一次ajax请求数据的所有...
    意识流丶阅读 69,922评论 2 70
  • 以前做分页的时候是每个需要分页的action下面写一大串分页的代码,今天就想可不可以将分页的代码单独写一个工具类,...
    renhandong阅读 2,678评论 0 1
  • 分页组件:** 功能:点击页面序号可以跳转到相应页面。点击上一页或者下一页,当页面在第一页时候上一页无法点...
    穆熙沐阅读 1,015评论 2 9
  • Ajax无刷新分页的必要性 具体实现: 商品总记录条数,每页显示多少条 mysql数据库关键字limit limi...
    周行知阅读 776评论 0 6