vue bootstrap 分页,可自定义按钮操作函数,自动监测每页数据数量修改,可修改分页元素显示数量

vue bootstrap有一个很强大的组件bootstrap-vue。但是这个组件的分页貌似并不支持前后端分离的分页。
我至少是没看出来。如果有看出来的请告诉我。
如果有用这个组件的同学可以跟我交流。
QQ:871966163
直通车bootstrap-vue

自己写了个分页组件,开箱即用。如有bug欢迎留言。
嫌麻烦大佬可以直通github,clone项目直接使用
vue-bootstrap-pagination

另外封装了一个 渲染函数&jsx的分页组件,有需要可以加QQ交流
jsx
组件

1、 参数

(1)props参数
  • total:数据总数,这个是必传参数。比如总数据有1000条,10000条。 数量为0,负数或者非数字字符串时,total取值为1,也就是最小值为1

  • size: 每一页的数据条数。比如每一页显示10条,15条。 数字为0,负数或者非数字字符串时,size取值为10

  • currentPage:分页初始页码,就是第一次进入有分页的这个页面显示的页码。记住是第一次数字为0,附属或者为非数字字符串时,currentPage取值为1,也就是最小值为1

这个数据是可以在操作分页的时候修改的,方便 vuex 记住当前页面,然后赋值初始页面,实现在第 N 页查看某一条数据进入另一个页面回来时还是会停留在第 N 页的效果,或者看到第 N 页了,点击其他页面,再点击回来,仍然会停留在第 N 页。

这个功能需要配合 \color{red}{getCurrentPage}

  • limit:分页元素。分页条显示的元素数量。数字小于5或者为非数字字符串时,limit取值为5,也就是最小值为5
    比如limit=5,会显示如下:
    分页元素为5

    分页条数为5

    分页条数为5

也就是除了左右两边箭头按钮会显示的分页元素数量

  • \color{blue}{align}:分页位置, left:左边,center:居中, right:右边。默认在左边

    左边

    align=center
    中间

    align=right
    右边.png

  • firstFunction:点击跳转到第一页触发函数

  • prevFunction:上一页按钮触发函数

  • currentFunction:点击页码触发函数

  • nextFunction:下一页按钮触发函数

  • lastFunction:最后一页按钮触发函数

  • sizeFunction:改变每页数量触发函数

  props: {
    //总数据
    total: {
      type: [Number, String],
      required: true
    },
    // 每页数量
    size: {
      type: [Number, String],
      default: 10
    },
    // 初始页码
    currentPage: {
      type: [Number, String],
      default: 1
    },
    // 分页显示数量
    limit: {
      type: [Number, String],
      default: 5
    },
    // 分页位置
    align: {
      default: "left",
      type: String
    },
    // 跳转第一页按钮触发函数
    firstFunction: {
      type: Function,
      required: true
    },
    // 上一页按钮触发函数
    prevFunction: {
      type: Function,
      required: true
    },
    // 点击页码触发函数
    currentFunction: {
      type: Function,
      required: true
    },
    // 下一页按钮触发函数
    nextFunction: {
      type: Function,
      required: true
    },
    // 最后一页按钮触发函数
    lastFunction: {
      type: Function,
      required: true
    },
    // 修改每页数量触发函数
    sizeFunction: {
      type: Function
    }
  },
(2)data参数
  • tempalteCurrentPage:分页当前页码。也就是激活的页码
  data() {
    return {
      tempalteCurrentPage: ""
    };
  },

2、 方法methods

  • toInteger:字符串转为数字类型
  • _firstFunction:跳转第一页按钮触发函数
  • _prevFunction:上一页按钮触发函数
  • _currentFunction:点击页码触发函数
  • _nextFunction:下一页按钮触发函数
  • _lastFunction:最后一页按钮触发函数
  • _sizeFunction:修改每页数量触发函数
  methods: {
    // 字符串转为数字类型 因为props会接收字符串,所以需要进行转换
    toInteger(val) {
      return parseInt(val, 10);
    },
    // 跳转第一页按钮触发函数
    _firstFunction() {
      if (this.firstFunction) {
        this.tempalteCurrentPage = 1;
        this.firstFunction();
      }
    },
    // 上一页按钮触发函数
    _prevFunction() {
      if (this.prevFunction) {
        this.tempalteCurrentPage = this.tempalteCurrentPage - 1;
        this.prevFunction();
      }
    },
    // 点击页码触发函数
    _currentFunction(item) {
      if (this.currentFunction) {
        this.tempalteCurrentPage = item;
        this.currentFunction();
      }
    },
    // 下一页按钮触发函数
    _nextFunction() {
      if (this.nextFunction) {
        this.tempalteCurrentPage = this.tempalteCurrentPage + 1;
        this.nextFunction();
      }
    },
    // 最后一页按钮触发函数
    _lastFunction() {
      if (this.lastFunction) {
        this.tempalteCurrentPage = this.nlyPgPages;
        this.lastFunction();
      }
    },
    // 修改每页数量触发函数
    _sizeFunction() {
      if (this.sizeFunction) {
        this.sizeFunction();
      }
    },
    // 分页元素添加上一页,最后一页,第一页,下一页等按钮
    _tempalteArray() {
      // this.nlyPgItemArray为 computed 中 nlyPgItemArray属性
      let nlyPgItemArrayAll = this.nlyPgItemArray;
      nlyPgItemArrayAll.splice(0, 0, "‹");
      nlyPgItemArrayAll.splice(0, 0, "‹‹");
      nlyPgItemArrayAll.push("›");
      nlyPgItemArrayAll.push("››");

      return nlyPgItemArrayAll;
    }
  },

3、 计算属性computed

  • nlyPgTotal:转换总页转为数字类型
  • nlyPgSize:每页数量转为数字类型
  • nlyPgCurrentPage:当前页数转为数字类型
  • nlyPgLimit:分页显示元素转为数字类型
  • nlyPgPages:计算总页数
  • nlyPgItemArray: 生成不包括上一页,下一页等按钮的分页元素
  • alignClass:分页位置
  • tempalteArray:生成包括最后一页,上一页,第一页,下一页等按钮的元素,最终分页元素
  computed: {
    // 转换总页转为数字类型
    nlyPgTotal: function() {
      return isNaN(this.toInteger(this.total))
        ? 1
        : this.toInteger(this.total) <= 0
        ? 1
        : this.toInteger(this.total);
    },
    // 每页数量转为数字类型
    nlyPgSize: function() {
      return isNaN(this.toInteger(this.size))
        ? 10
        : this.toInteger(this.size) <= 0
        ? 10
        : this.toInteger(this.size);
    },
    // 当前页数转为数字类型
    nlyPgCurrentPage: function() {
      return this.toInteger(this.tempalteCurrentPage);
    },
    // 分页显示元素转为数字类型
    nlyPgLimit: function() {
      return isNaN(this.toInteger(this.limit))
        ? 5
        : this.toInteger(this.limit) <= 4
        ? 5
        : this.toInteger(this.limit);
    },
    // 计算总页数
    nlyPgPages: function() {
      return Math.ceil(this.nlyPgTotal / this.nlyPgSize);
    },
    // 生成不包括上一页,下一页等按钮的分页元素
    nlyPgItemArray: function() {
      if (
        this.nlyPgCurrentPage + 1 <= this.nlyPgLimit &&
        this.nlyPgPages < this.nlyPgLimit
      ) {
        // 当前页码+1小于分页元素且总页数大于分页元素
        const itemList = Array.from({ length: this.nlyPgPages }).map(
          (v, k) => k + 1
        );
        return itemList;
      } else if (
        this.nlyPgCurrentPage + 1 <= this.nlyPgLimit &&
        this.nlyPgPages == this.nlyPgLimit
      ) {
        // 当前页码+1小于分页元素且总页数等于分页元素
        const itemList = Array.from({ length: this.nlyPgLimit }).map(
          (v, k) => k + 1
        );
        return itemList;
      } else if (
        this.nlyPgCurrentPage + 2 <= this.nlyPgLimit &&
        this.nlyPgPages > this.nlyPgLimit
      ) {
        // 当前页码+2小于分页元素且总页数大于分页元素
        const itemList = Array.from({ length: this.nlyPgLimit - 1 }).map(
          (v, k) => k + 1
        );
        itemList.push("···");
        return itemList;
      } else if (
        this.nlyPgPages - this.nlyPgCurrentPage + 2 < this.nlyPgLimit &&
        this.nlyPgPages > this.nlyPgLimit
      ) {
        // 总页数-当前页码+2小于分页元素且总页数大于分页元素
        const itemList = Array.from({ length: this.nlyPgLimit - 1 }).map(
          (v, k) => k + (this.nlyPgPages - this.nlyPgLimit + 2)
        );
        itemList.splice(0, 0, "···");
        return itemList;
      } else if (
        // 总页数-当前页码+2小于分页元素且总页数等于分页元素
        this.nlyPgPages - this.nlyPgCurrentPage + 2 < this.nlyPgLimit &&
        this.nlyPgPages == this.nlyPgLimit
      ) {
        const itemList = Array.from({ length: this.nlyPgLimit - 1 }).map(
          (v, k) => k + (this.nlyPgPages - this.nlyPgLimit + 2)
        );
        return itemList;
      } else {
        // 其他情况
        const itemList = Array.from({ length: this.nlyPgLimit - 2 }).map(
          (v, k) =>
            k + this.nlyPgCurrentPage - Math.ceil(this.nlyPgLimit / 2) + 2
        );
        itemList.splice(0, 0, "···");
        itemList.push("···");
        return itemList;
      }
    },
    // 分页位置
    alignClass: function() {
      const align = this.align;
      if (align === "center") {
        return "justify-content-center";
      } else if (align === "end" || align === "right") {
        return "justify-content-end";
      }
      return "";
    },
    // 生成包括最后一页,上一页,第一页,下一页等按钮的元素,最终分页元素
    tempalteArray: function() {
      return this._tempalteArray();
    }
  },

4、 页面渲染created生命周期

  created() {
    // 初始化初始页面
    this.tempalteCurrentPage = isNaN(this.toInteger(this.currentPage))
      ? 1
      : this.toInteger(this.currentPage) <= 1
      ? 1
      : this.toInteger(this.currentPage);
  },

5、 页面监控watch

  watch: {
    // 暴露当前页码给父组件(变化之前的,如果从第4页跳转到第5页,父组件获取的值是4)
    tempalteCurrentPage: function() {
      this.$emit("getCurrentPage", this.tempalteCurrentPage);
    },
    // 监测父组件传入的初始页码currentPage,发生变化就给分页当前页码赋值
    currentPage: function(newval, oldval) {
      if (newval != oldval) {
        this.tempalteCurrentPage = this.toInteger(this.currentPage);
      }
    },
    // 监测总页数,当页数(即总数量发生变化的时候),如果当前页码大于总页数,当前页码变为最大页面,否则不变,
    nlyPgPages: function(newval, oldval) {
      if (newval != oldval) {
        this.tempalteCurrentPage =
          this.tempalteCurrentPage > newval ? newval : this.tempalteCurrentPage;
      }
    },
    // 监测每页数量变化,发生变化的时候,重新执行_sizeFunction(),不传入组件参数sizeFunction也会执行。
    nlyPgSize: function(newval, oldval) {
      if (newval != oldval) {
        this._sizeFunction();
      }
    }
  }

6、 css

<style>
.nly-pagination-item {
  cursor: pointer;
  color: #007bff;
}
</style>

7、 template

<template>
  <ul :class="'pagination ' + alignClass">
    <template v-for="(item, index) in tempalteArray">
      <!-- 跳转第一页按钮 -->
      <template v-if="item == '‹‹'">
        <!-- 当前页面为第一页的时候禁用 -->
        <li
          class="page-item disabled"
          :key="index"
          v-if="nlyPgCurrentPage == 1"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
        <!-- 当前页面不为第一页的时候 -->
        <li
          class="page-item nly-pagination-item"
          :key="index"
          v-else
          @click="_firstFunction"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
      </template>

      <!-- 上一页按钮 -->
      <template v-else-if="item == '‹'">
        <!-- 当前页面为第一页的时候禁用 -->
        <li
          class="page-item disabled"
          :key="index"
          v-if="nlyPgCurrentPage == 1"
        >
          <a class="page-link"> {{ item }}</a>
        </li>

        <!-- 当前页面不为第一页的时候 -->
        <li
          class="page-item nly-pagination-item"
          :key="index"
          v-else
          @click="_prevFunction"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
      </template>

      <!-- 省略按钮 禁用 -->
      <template v-else-if="item == '···'">
        <li class="page-item disabled" :key="index">
          <a class="page-link"> {{ item }}</a>
        </li>
      </template>

      <!-- 跳转到最后一页按钮 -->
      <template v-else-if="item == '››'">
        <!-- 当前页面为最后一页的时候禁用 -->
        <li
          class="page-item disabled"
          :key="index"
          v-if="nlyPgCurrentPage == nlyPgPages"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
        <!-- 当前页面不为最后一页的时候 -->
        <li
          class="page-item nly-pagination-item"
          :key="index"
          v-else
          @click="_lastFunction"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
      </template>

      <!-- 下一页按钮 -->
      <template v-else-if="item == '›'">
        <!-- 当前页面为最后一页的时候禁用 -->
        <li
          class="page-item disabled"
          :key="index"
          v-if="nlyPgCurrentPage == nlyPgPages"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
        <!-- 当前页面不为最后一页的时候 -->
        <li
          class="page-item nly-pagination-item"
          :key="index"
          v-else
          @click="_nextFunction"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
      </template>

      <!-- 当前页码激活状态 -->
      <template v-else-if="item == tempalteCurrentPage">
        <li
          class="page-item active nly-pagination-item"
          :key="index"
          @click="_currentFunction(item)"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
      </template>

      <!-- 点击跳转页码 -->
      <template v-else>
        <li
          class="page-item nly-pagination-item"
          :key="index"
          @click="_currentFunction(item)"
        >
          <a class="page-link"> {{ item }}</a>
        </li>
      </template>
    </template>
  </ul>
</template>

8、 组件

  • 1 新建一个vue项目,过程省略。这里用的vue cli3以上版本。
    目录如下


    目录
  • 2 在components下建立一个NLYpagination.vue和index.js


    新建文件

vue文件名字随意,index最好不改,如果改了在接下来的main.js引入的时候也有改。
把上面的代码放到NLYpagination.vue中。

  • 注册组件

打开刚刚建立的index.js,写入以下代码。注意import路径

import NLYpagination from "../components/NLYpagination.vue";

export default {
  install: Vue => {
    Vue.component("NLY-pagination", NLYpagination);
  }
};

在main.js中引入添加以下代码引入index.js

import pagination from "./components/index.js";
Vue.use(pagination);

完整的main.js应该是这样

main.js

9、 demo

在需要分页组件的地方,使用组件就行。

<template>
    <NLY-pagination
      ref="pagination"
      :total="total"
      :size="size"
      :limit="limit"
      align="center"
      :currentPage="currentPage"
      :firstFunction="firstFunction"
      :prevFunction="prevFunction"
      :currentFunction="currentFunction"
      :nextFunction="nextFunction"
      :lastFunction="lastFunction"
      :sizeFunction="sizeFunction"
      @getCurrentPage="getCurrentPage"
    />
</template>
<script>
export default {
  data() {
    return {
      currentPage: 1,
      total: 100,
      size: 10,
      limit: 5
    };
  },
  methods: {
    firstFunction() {
      console.log(
        `跳到第一页: 从第 ${this.currentPage} 页跳转到 ${this.$refs["pagination"].tempalteCurrentPage} 页`
      );
    },
    prevFunction() {
      console.log(
        `跳到上一页: 从第 ${this.currentPage} 页跳转到 ${this.$refs["pagination"].tempalteCurrentPage} 页`
      );
    },
    currentFunction() {
      console.log(
        `点击跳转到当前点击页码页面: 从第 ${this.currentPage} 页跳转到 ${this.$refs["pagination"].tempalteCurrentPage} 页`
      );
    },
    nextFunction() {
      console.log(
        `跳到下一页: 从第 ${this.currentPage} 页跳转到 ${this.$refs["pagination"].tempalteCurrentPage} 页`
      );
    },
    lastFunction() {
      console.log(
        `跳到最后一页: 从第 ${this.currentPage} 页跳转到 ${this.$refs["pagination"].tempalteCurrentPage} 页`
      );
    },
    sizeFunction() {
      console.log("修改每页数量");
    },
    getCurrentPage(data) {
      this.currentPage = data;
    },
    getPages(val) {
      console.log(val);
    }
  }
};
</script>
<!--
total: 总数
size: 每页数量,默认10
currentPage: 初始页码
limit: 显示页码个数
align:分页位置,left左边,center中间,right右边,默认左边
firstFunction: 第一页按钮函数
prevFunction: 上一页按钮函数
currentFunction: 点击页码函数
nextFunction: 下一页页码函数
lastFunction: 最后一页页码函数
sizeFunction: 修改每页数量自动执行函数
 -->

演示效果如下:


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

推荐阅读更多精彩内容

  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,198评论 0 6
  • 本篇文章是一篇Vue.js的教程,目标在于用一种常见的业务场景——分页/无限加载,帮助读者更好的理解Vue.js中...
    ElToro阅读 4,152评论 0 44
  • 主要还是自己看的,所有内容来自官方文档。 介绍 Vue.js 是什么 Vue (读音 /vjuː/,类似于 vie...
    Leonzai阅读 3,324评论 0 25
  • 感赏自己坚持读书,抓紧一切时间听老师的音频,勤练基本功,积蓄能量提升自己。 感赏自己在看到孩子晚上又出去时,保持心...
    风景_6b35阅读 207评论 0 8
  • 半隐于江湖 【二月寻嵩】 第一次听说许嵩是因为朋友阿...
    二月寻嵩阅读 238评论 1 3