Super detailed: a beautiful Vue pager component implementation

 The whole article is divided into two parts:

Idea part: explain how to implement the pager component [take a lot of time to see-suggestion]

The latter part: Follow the steps to directly introduce components [no time to read-suggestion]

Idea: judge based on consecutive page numbers

  • In the component (Search component) that needs to add a pager

          <!-- 分页器 -->
          <Pagination
            :pageNo="searchParams.pageNo"
            :pageSize="searchParams.pageSize"
            :total="total"
            :continues="5"
            @getPageNo="getPageNo"
          />
  1. Pass [current page number pageNo], [data pageSize displayed on each page], [total data total], [continuous page number (important)] on the pager component , and define a [custom event getPageNo] to get the [ The current page number pageNo] is passed back, and the data request is made
  2. The function defined in methods accepts the [current page pageNo] returned by the pager

  1. The pager is divided into three parts ------[as shown below]

  • In the pager component (Pagination)

        1. Obtain the parameters passed by the Search component through props

     props: ["pageNo", "pageSize", "total", "continues"],

        2. Calculate the total number of pages/last page in the computed property of the pager component -  this.total / this.pageSize

[Remember to round up Math.ceil() , for example: when the total data total=30, each page data pageSize=3, then 10 pages are just displayed, if each page data pageSize=4, there are 7 pages to display There are 4 pieces of data, and 2 pieces need to be displayed on the next page, so round up, Math.ceil(30/4 )=8

        3. Calculate the start number start and end number end of continuous page numbers [at least 5 pages] in the computed attribute of the pager component [ the current page pageNo is in the continuous page number ]

  • Situation Judgment 1: Consecutive page numbers > total number of pages [start=1, end=total number of pages]
  • Judgment 2: Continuous page numbers < total number of pages [Calculate start = pageNo - parseInt(continues / 2), end = pageNo + parseInt(continues / 2);]
    • Case 1: The start number appears 0 | negative number [continues=5, pageNo=1, 2]
    • Case 2: end number is greater than the total page number [continues=5, totalPage=30, pageNo=29, 30]
  • Remember: return start and end at the end

  • Judgment of the previous page, the first page, and the last page

    • Previous page: If the current page pageNo=1, the previous page button will not be displayed, bind the click event, click to trigger the getPageNo custom event, pass the current page pageNo-1 as a parameter back to the search component, and request the data of the previous page
    • First page: If the starting number of the continuous page number start>1, the first page defined above will be displayed; if it is smaller than that, the first page button in the continuous page number will be displayed. The click event is the same as above, because it may handle the selected state, so bind a class [already defined in css], add the selected color, of course, you need to judge whether it is the selected page
    • Omit...Small point: When the start=3 of consecutive page numbers, it is displayed, which means that there is another page between them
    • Continuous page numbers: Use v-for to traverse the numbers, traverse the end in the continuous page numbers, and judge the element page>start, and then display [Because the continuous page number passed is 5, the largest continuous page number in the pager is end- start=5, remove the page number before start, so that the continuous page number is 5], the other is the same as above
    • Omit...Small point | Last page | Next page: Same calculation as above [totalPage is the total number of pages that have been calculated above | Last page]

  • static component

<template>
  <div class="pagination">
    <button>1</button>
    <button>上一页</button>
    <button>···</button>

    <button>3</button>
    <button>4</button>
    <button>5</button>
    <button>6</button>
    <button>7</button>
    
    <button>···</button>
    <button>9</button>
    <button>上一页</button>
    
    <button style="margin-left: 30px">共 60 条</button>
  </div>
</template>

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

<style lang="less" scoped>
  .pagination {
    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;
      }
    }
  }
</style>

 

1. Register components

Note: There are many places where the pager component is generally used, so I registered it as a global component

  • Configure in main.js of vue scaffolding

 2. Mount components

  • Mount and pass parameters

[current page number pageNo], [data pageSize displayed on each page], [total data total], [continuous page number (important)], define a [custom event getPageNo] to pass back the [current page number pageNo] clicked by the user , and make a data request

  • The custom event accepts the parameter of the current page, and sends the request again [according to your own]

 3. Pager component code

<template>
  <div class="pagination">
    <button :disabled="pageNo == 1" @click="$emit('getPageNo', pageNo - 1)">
      上一页
    </button>
    <button
      v-if="startNumAndEndNum.start > 1"
      @click="$emit('getPageNo', 1)"
      :class="{ active: pageNo == 1 }"
    >
      1
    </button>
    <button v-if="startNumAndEndNum.start > 2">···</button>

    <!-- 连续的页码 -->
    <button
      v-for="(page, index) in startNumAndEndNum.end"
      :key="index"
      v-if="page >= startNumAndEndNum.start"
      @click="$emit('getPageNo', page)"
      :class="{ active: pageNo == page }"
    >
      {
   
   { page }}
    </button>

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

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

<script>
export default {
  name: "Pagination",
  props: ["pageNo", "pageSize", "total", "continues"],

  computed: {
    // *计算总共多少页,也就是最后一页(需要向上取整Math.ceil)
    totalPage() {
      return Math.ceil(this.total / this.pageSize);
    },

    // *计算出连续页码的起始数字与结束的数字【连续的页码数字:至少是5】
    startNumAndEndNum() {
      const { continues, pageNo, totalPage } = this; // 解构了
      // 先定义两个变量存储起始数字与结束数字
      let start = 0,
        end = 0;
      // *连续页码数字是5【至少5页】,如果出现不正常现象【不够5页,即总页数 < 连续页码5】
      if (continues > totalPage) {
        start = 1;
        end = totalPage;
      } else {
        // 正常现象【连续的页码5,但是你的总页数一定是大于5的】 parseInt()返回一个十进制的整数【一个数字的参数可同Math.floor】
        start = pageNo - parseInt(continues / 2);
        end = pageNo + parseInt(continues / 2);
        // 把出现不正常的现象【start数字出现0|负数,continues=5,pageNo=1、2的时候】
        if (start < 1) {
          start = 1;
          end = continues;
        }
        // 把出现不正常的现象【end数字大于总页码,continues=5,totalPage=30,pageNo=29、30的时候】
        if (end > totalPage) {
          start = totalPage - continues + 1;
          end = totalPage;
        }
      }
      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属性的所有元素
    &[disabled] {
      color: #c0c4cc;
      cursor: not-allowed;
    }

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

The pager of the python-django framework handwritten before:

Paging implementation of django database version

Guess you like

Origin blog.csdn.net/weixin_49931650/article/details/127828464