0005-网页网站分页器思路(两种方案)


  • 代码优劣势
  • 版本1(推荐)
    • 思路
    • 参数说明(来源父传子)
    • 完整代码
  • 版本2(自写)
    • 思路
    • 参数说明(来源父传子)
    • 完整代码

说明:主要表述分页显示效果时的思路

代码优劣势

  • 版本2优势
    • 如果总页码数量够多(大于等于9页),那么从进入页面开始到切换任意某个页面时,分页器的DOM都是固定的,视觉效果好。
  • 版本2劣势
    • 没有使用 continues 这个值,即不能自定义中间连续页的个数,可复用性差。

版本1(推荐)

思路

  1. 计算出总共多少页(向上取整(总个数 / 每一页显示的数));
  2. 根据要求中间显示多少页的个数,来进行计算出中间页的页码数(本例中默认给的参数continues[来自props传参]);
  3. 再根据中间页的开始和结尾页码来判定是否显示其前面的部分与后面的部分(见图示);
  • 中间页码起始值与结束值计算过程解析
  1. 开头处的页码 1··· 显示,与尾处的显示说明见图;
  • button1的显示解析
  • button2显示解析(即···显示条件判定)
  • 结尾页码显示与倒数第二页···的显示解析
  1. 京东显示图示。
  • 京东分页器图示

参数说明(来源父传子)

  • props: ["pageNo", "pageSize", "total", "continues"],
    • pageNo 当前显示的页码数;
    • pageSize 每一页能显示多少个;
    • total 共多少条数据;
    • continues 中间页(连续部分)页码要求是多少个(本例中为5)。

完整代码

<template>
  <div class="pagination">
    <!-- 如果 选择页 pageNo 为第一页时,则禁止按钮使用 -->
    <button :disabled="pageNo == 1">
      上一页
    </button>
    <!-- 如果 计算结果startNumAndEndNum.start > 1,意味着中间部分的页码数是从2及以上开始显示的,则需要显示1 -->
    <!-- 因为如果pageNo(当前页)为1、2、3时算出来的start都为1,则pageNo=4时,才会显示 -->
    <button
      v-if="startNumAndEndNum.start > 1"
      @click="$emit('update:pageNo', 1)"
      :class="{ active: pageNo == 1 }"
    >
      1
    </button>
    <!-- 当start > 2时,即最小为start = 3时显示...(这里个人觉得不严谨:如果为3时应该显示2;不过京东也是这样显示的[见说明图]) -->
    <button v-if="startNumAndEndNum.start > 2">···</button>
    <!-- 中间部分 -->
    <!-- 遍历最大的值会生成数组,比如end是9,则为[1, 2, 3, 4, 5, 6, 7, 8, 9] -->
    <!-- 此时我们只需要保留大于等于 start的值的部分即可,即[5, 6, 7, 8, 9] -->
    <button
      v-for="(page, index) in startNumAndEndNum.end"
      :key="index"
      v-if="page >= startNumAndEndNum.start"
      @click="$emit('update:pageNo', page)"
      :class="{ active: pageNo == page }"
    >
      {{ page }}
    </button>

    <!-- 下 -->
    <button v-if="startNumAndEndNum.end < totalPage - 1">···</button>
    <button
      v-if="startNumAndEndNum.end < totalPage"
      @click="$emit('update:pageNo', totalPage)"
      :class="{active:pageNo==totalPage}"
    >
      {{ totalPage }}
    </button>
    <button
      :disabled="pageNo == totalPage"
      @click="$emit('update:pageNo', pageNo + 1)"
    >
      下一页
    </button>

    <button style="margin-left: 30px">共 {{ total }} 条</button>
    <!-- <el-empty description="描述文字aaaaaaaaaa"/> -->

  </div>
</template>

<script>
export default {
  name: "Pagination",
  props: ["pageNo", "pageSize", "total", "continues"],
  computed: {
    //总共多少页
    totalPage() {
      //向上取证
      return Math.ceil(this.total / this.pageSize);
    },
    //计算出连续的页码的起始数字与结束数字[连续页码的数字:至少是5]
    startNumAndEndNum() {
      const { continues, pageNo, totalPage } = this;
      //先定义两个变量存储起始数字与结束数字
      let start = 0,
        end = 0;
      //连续页码数字5【就是至少五页】,如果出现不正常的现象【就是不够五页】
      //不正常现象【总页数没有连续页码多】
      if (continues > totalPage) {
        start = 1;
        end = totalPage;
      } else {
        //正常现象【连续页码5,但是你的总页数一定是大于5的】
        //起始数字
        start = pageNo - parseInt(continues / 2);
        //结束数字
        end = pageNo + parseInt(continues / 2);
        //把出现不正常的现象【start数字出现0|负数】纠正
        // 因为pageNo可能比较小,出现负数
        if (start < 1) {
          start = 1;
          end = continues;
        }
        //把出现不正常的现象[end数字大于总页码]纠正
        if (end > totalPage) {
          end = totalPage;
          start = totalPage - continues + 1;
        }
      }
      return { start, end };
    },
  },
};
</script>

<style lang="less" scoped>
.pagination {
  text-align: center;
  button {
    margin: 0 5px;
    background-color: #f4f4f5;
    color: #606266;
    outline: none;
    border-radius: 2px;
    padding: 0 4px;
    vertical-align: top;
    display: inline-block;
    font-size: 13px;
    min-width: 35.5px;
    height: 28px;
    line-height: 28px;
    cursor: pointer;
    box-sizing: border-box;
    text-align: center;
    border: 0;

    &[disabled] {
      color: #c0c4cc;
      cursor: not-allowed;
    }

    &.active {
      cursor: not-allowed;
      background-color: #409eff;
      color: #fff;
    }
  }
}
.active{
  background: skyblue;
}
</style>

版本2(自写)

思路

  1. 计算出总共多少页(向上取整(总个数 / 每一页显示的数));
  2. 根据要求中间显示多少页的个数,来进行计算出中间页的页码数(本例中默认给的参数continues[来自props传参]),分几种情况来判定即可;
  3. 总长度在【3 - 7】之间;
  4. 总长度等于【8 或 9】或 总长度大于9但所选页码【<= 5】时(这里应该也是属于下面一点的情况之一,但是其中间连续页显示的结果与此条一致,所以放在这里讨论);
  5. 其余都是考虑总长度大于9的:
    1. 总长度大于9,所选页码【5 < pageNo < (len - 4)】;
    2. 总长度大于9,所选页码【pageNo >= (len - 4)】。
  6. 再处理尾部的两个分页器显示即可(具体见代码)。
  • 图示
    • 分页器自写版之第2位按钮显示讲解
    • 分页器自写版之中间连续页按钮显示讲解

参数说明(来源父传子)

  • props: ["pageNo", "pageSize", "total", "continues"],
    • pageNo 当前显示的页码数;
    • pageSize 每一页能显示多少个;
    • total 共多少条数据;
    • continues 中间页(连续部分)页码要求是多少个(本例中为5,且不能更改)。

完整代码

<template>
  <div class="pagination" v-show="needShowPag" @click="handleShow($event)">
    <button>上一页</button>
    <!-- 如果显示则肯定是显示2页及以上,所以前两个不用判断 -->
    <button :class="{ active: pageNo === 1 }">1</button>
    <button
      :class="{ active: pageNo === 2 }"
      :disabled="typeof secondPagShow !== 'number'"
    >
      {{ secondPagShow }}
    </button>

    <button
      :class="{ active: pageNo === pag }"
      v-for="(pag, index) in middlePagShow"
      :key="index"
    >
      {{ pag }}
    </button>

    <button
      :class="{ active: pageNo === penultimatePagShow }"
      v-if="penultimatePagShow"
      :disabled="typeof penultimatePagShow !== 'number'"
    >
      {{ penultimatePagShow }}
    </button>
    <button :class="{ active: pageNo === endPagShow }" v-if="endPagShow">
      {{ endPagShow }}
    </button>
    <button>下一页</button>

    <button style="margin-left: 30px">共 {{ totalData }} 条</button>
  </div>
</template>

<script>
export default {
  name: "Pagination",

  props: {
    totalData: Number,
    continues: Number,

    // 以下两个props通过sync修饰符的方式来传递的
    pageNo: Number,
    pageSize: Number,
  },
  data() {
    return {
      pagLength: 0, // 整个页码的长度
    };
  },
  computed: {
    // 是否需要展示分页器(需要展示的总数据 > 分页的数据)
    needShowPag() {
      return this.totalData > this.pageSize;
    },

    // 处理第二页分页情况
    secondPagShow() {
      let len = this.pagLength;
      // 如果长度在3-9之间的话,本来就能能显示9个,则显示页码2的概率为100%;
      if (len >= 3 && len <= 9) {
        return 2;
      } else {
        //! 总的超过9页了,那么肯定会有 (•••) 显示;
        //! 当前选择的页码数 > 3时, 2号位100%显示(•••)
        console.log("second");
        return this.pageNo > 3 ? "•••" : 2;
      }
    },

    // 处理中间页
    middlePagShow() {
      let len = this.pagLength;
      // 上来先置空
      let pagAry = []; // 存放中间页码的
      // 最多存放5位,并且总页面数如果在3-9之间都是存放[3, 4, 5, 6, 7]这几个数
      console.log("init", len, this.pageNo);
      if (len >= 3 && len <= 7) {
        for (let pag = 3; pag <= len; pag++) {
          pagAry.push(pag);
        }
      } else if ([8, 9].includes(len) || (len > 9 && this.pageNo <= 5)) {
        pagAry = [3, 4, 5, 6, 7];
      } else if (len > 9 && this.pageNo > 5 && this.pageNo < len - 4) {
        //! 最后至少要有4位空余(尾号2位,中间5位数组的后两位),则为len-4
        // 所选位置(中间位置为this.pageNo,则取前后各两位,组成5位数的数组)
        /* for (let pag = this.pageNo - 2; pag <= this.pageNo + 3; pag++) {
          pagAry.push(pag);
        } */
        pagAry = [
          this.pageNo - 2,
          this.pageNo - 1,
          this.pageNo,
          this.pageNo + 1,
          this.pageNo + 2,
        ];
      } else if (len > 9 && this.pageNo >= len - 4) {
        console.log("last");
        for (let pag = len - 6; pag <= len - 2; pag++) {
          pagAry.push(pag);
        }
        // pagAry = [len - 6, len - 5, len - 4, len - 3, len - 2];
      }
      return pagAry;
    },

    // 处理 倒数 第二个分页情况
    penultimatePagShow() {
      let len = this.pagLength;
      // 如果长度在3-9之间的话,本来就能能显示9个,则显示页码2的概率为100%;
      if (len === (8 || 9)) {
        return 8;
      } else if (len > 9) {
        //! 总的超过9页了,那么肯定会有 (•••) 显示;
        //! 当前选择的页码数 > 总数 - 5 时,则意味着一定显示的是倒数第二个数值
        return this.pageNo > len - 5 ? len - 1 : "•••";
      } else {
        // 如果总数都在8以下,则不显示
        return 0;
      }
    },

    // 处理 最后一个 分页情况
    endPagShow() {
      let len = this.pagLength;
      // 如果长度在3-9之间的话,本来就能能显示9个,则显示页码2的概率为100%;
      if (len === 8) {
        return 0;
      } else if (len >= 9) {
        //! 总的超过9页了,那么肯定会有 (•••) 显示;
        //! 当前选择的页码数 > 总数 - 5 时,则意味着一定显示的是倒数第二个数值
        return len;
      }
    },
  },
  methods: {
    // 处理点击事件
    handleShow(ev) {
      if (ev.target.tagName.toLowerCase() === "button") {
        // 如果点击的是数字分页器按钮(不含...的)
        if (ev.target.innerText.match(/^\d+$/)) {
          let clickNum = ev.target.innerText.match(/^\d+$/)[0];
          console.log("点击的是:数字分页器", clickNum);
          // this.pageNo = clickNum;
          // 自定义事件方式
          // this.$emit('changePageNo', Number(clickNum));
          // 使用 sync 修饰符的方式.
          this.$emit("update:pageNo", Number(clickNum));
        }
      }
    },
  },
  watch: {
    // 如果totalData数据变了,则自身的pagLength也会变
    totalData: {
      immediate: true,
      handler(newValue) {
        // 向上取整
        this.pagLength = Math.ceil(newValue / this.pageSize);
        console.log(this.pagLength);
      },
    },
  },
};
</script>

<style lang="less" scoped>
.pagination {
  text-align: center;
  button {
    margin: 0 5px;
    background-color: #f4f4f5;
    color: #606266;
    outline: none;
    border-radius: 2px;
    padding: 0 4px;
    vertical-align: top;
    display: inline-block;
    font-size: 13px;
    min-width: 35.5px;
    height: 28px;
    line-height: 28px;
    cursor: pointer;
    box-sizing: border-box;
    text-align: center;
    border: 0;

    &[disabled] {
      // color: #c0c4cc;
      background-color: #ffffff;
      cursor: not-allowed;
      border: none;
    }

    &.active {
      // cursor: not-allowed;
      background-color: #409eff;
      color: #fff;
    }
  }
}
</style>

文章作者: HConan
文章链接: https://www.hconan.com/posts/6d28b5c0.html
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 HConan !
 上一篇
下一篇 
0004-使用hexo、腾讯云轻量应用服务器搭建博客教程 0004-使用hexo、腾讯云轻量应用服务器搭建博客教程
2022-01-08 blog
  目录

深圳SEO优化公司衢州网站搜索优化湘西关键词按天扣费报价吉林百姓网标王推广漯河网络广告推广价格阿坝网站关键词优化价格永湖网站优化哪家好抚顺英文网站建设推荐大芬百度seo价格昌都seo优化推荐龙岩网站搜索优化价格怒江百度爱采购多少钱漳州百度seo哪家好塘坑品牌网站设计垦利百度网站优化哪家好南澳建网站推荐邵阳网络推广公司昭通关键词排名包年推广价格民治网站制作多少钱钦州关键词排名公司石家庄网站改版价格南联英文网站建设西安网站优化按天收费价格思茅至尊标王多少钱龙岩企业网站设计价格咸阳优化哪家好酒泉百姓网标王哪家好佛山网站制作设计哪家好苏州如何制作网站舟山百姓网标王推广公司泉州网站制作设计价格歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

深圳SEO优化公司 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化