【问题标题】:How to limit pagination buttons in Vue?如何限制 Vue 中的分页按钮?
【发布时间】:2021-01-23 10:15:30
【问题描述】:

我有一个分页组件,它接收totalPagescurrentPage 道具,然后呈现更改currentPage 的按钮。问题是现在如果我有很多产品,我会渲染太多按钮,我想将按钮的数量限制为 5 个 - 前两页、当前页和后两页。

所以如果我的当前页面是4,我会看到页面2, 3, 4, 5, 6 的按钮,并且当前页面始终是中间按钮(除非这是不可能的)。我不太确定如何处理这个问题,尤其是当currentPage 是第一个/第二个或倒数第二个/最后一个时的极端情况。

<template lang="html">
    <div class="pagination">
        <div v-for="page in totalPages">
            <div class="page" :class="{ active: page == currentPage}"  @click="setCurrentPage(page)">{{ page }}</div>
        </div>
    </div>
</template>

<script>
export default {
    props: ["totalPages", "currentPage"],
    methods: {
        setCurrentPage(page){
            this.$emit("setCurrentPage", page);
        }
    }
}
</script>

【问题讨论】:

    标签: javascript vue.js vuejs2 pagination vue-component


    【解决方案1】:

    对于在极端情况下也显示完整集的分页,请使用以下算法。这个想法是计算正确的起始索引,然后根据它生成一个数组:

    computed: {
      pages() {
        let numShown = 5;   // This sets the number of page tabs
        numShown = Math.min(numShown, this.totalPages);
        let first = this.currentPage - Math.floor(numShown / 2);
        first = Math.max(first, 1);
        first = Math.min(first, this.totalPages - numShown + 1);
        return [...Array(numShown)].map((k,i) => i + first);
      }
    }
    

    这是一个演示(我更改了一些变量名):

    Vue.component('child', {
      props: ["total", "current"],
      template: `
      <div class="pagination">
        <template v-for="page in pages">
          <div
            :class="{ active: page == current }" class="page no-select"
            @click="setCurrent(page)"
          >
            {{ page }}
          </div>
        </template>
      </div>
      `,
      data: () => ({
        numShown: 5
      }),
      computed: {
        pages() {
          const numShown = Math.min(this.numShown, this.total);
          let first = this.current - Math.floor(numShown / 2);
          first = Math.max(first, 1);
          first = Math.min(first, this.total - numShown + 1);
          return [...Array(numShown)].map((k,i) => i + first);
        }
      },
      methods: {
        setCurrent(page){
          this.$emit("set", page);
        }
      }
    })
    
    new Vue({
      el: "#app",
      data: () => ({
        total: 8,
        current: 1
      })
    });
    .page {
      display: inline-block;
      background: #dddddd;
      padding: 6px 16px;
      cursor: pointer;
      font-family: 'Helvetica';
      font-size: 13pt;
    }
    .active {
      background: #ddeeff;
      font-weight: bold;
    }
    .no-select {
      user-select: none;
      -o-user-select:none;
      -moz-user-select: none;
      -khtml-user-select: none;
      -webkit-user-select: none;
    }
    <div id="app">
      <child :total="total" :current="current" @set="current = $event"></child>
    </div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

    【讨论】:

      【解决方案2】:

      如下创建一个计算属性:

      <template lang="html">
          <div class="pagination">
              <div v-for="page in displayPages"> <!--change here -->
                  <div class="page" :class="{ active: page == currentPage}"  @click="setCurrentPage(page)">{{ page }}</div>
              </div>
          </div>
      </template>
      
      <script>
      export default {
        props: ["totalPages", "currentPage"],
        computed: {
          /* old
          displayPages() {
            return [-2, -1, 0, 1, 2].map(num => num + this.currentPage).filter(num => num <= totalPages && num > 0);
            // produces array of 5 or less
            // currentPage = 1 -> return [1, 2]
            // current page = 8(last) -> [6, 7, 8]
          },*/
          displayPages() {
            const totalPages = this.totalPages;
            let currentPage = this.currentPage;
            if ([1, 2].includes(currentPage)) currentPage = 3;
            else if ([totalPages -1, totalPages].includes(currentPage)) currentPage = totalPages - Math.trunc(5 / 2);
            
            return [...Array(5).keys()].map(i => i - Math.trunc(5 / 2) + currentPage)
          }
        },
        methods: {
          setCurrentPage(page){
            this.$emit("setCurrentPage", page);
          }
        }
      }
      </script>
      

      它应该限制按钮和可扩展性;只需将数组更改为缩放即可。

      更新: 答案根据 Dans 的建议更新,产生以下输出

      total pages = 20
      cp = current page
      cp |   return
      ---------------------
      1   [ 1, 2, 3, 4, 5 ]
      2   [ 1, 2, 3, 4, 5 ]
      3   [ 1, 2, 3, 4, 5 ]
      4   [ 2, 3, 4, 5, 6 ]
      5   [ 3, 4, 5, 6, 7 ]
      6   [ 4, 5, 6, 7, 8 ]
      7   [ 5, 6, 7, 8, 9 ]
      8   [ 6, 7, 8, 9, 10 ]
      9   [ 7, 8, 9, 10, 11 ]
      10  [ 8, 9, 10, 11, 12 ]
      11  [ 9, 10, 11, 12, 13 ]
      12  [ 10, 11, 12, 13, 14 ]
      13  [ 11, 12, 13, 14, 15 ]
      14  [ 12, 13, 14, 15, 16 ]
      15  [ 13, 14, 15, 16, 17 ]
      16  [ 14, 15, 16, 17, 18 ]
      17  [ 15, 16, 17, 18, 19 ]
      18  [ 16, 17, 18, 19, 20 ]
      19  [ 16, 17, 18, 19, 20 ]
      20  [ 16, 17, 18, 19, 20 ]
      
      

      【讨论】:

      • 理想情况下,第 1 页应显示 1-2-3-4-5。显示 1-2-3 然后 1-2-3-4 然后 1-2-3-4-5 有点不自然
      猜你喜欢
      • 2016-03-04
      • 2023-03-11
      • 2014-08-14
      • 1970-01-01
      • 2019-10-23
      • 2019-05-21
      • 2021-08-23
      • 1970-01-01
      • 2018-03-03
      相关资源
      最近更新 更多