面向Vue新人:用Vue寫一個分頁器

以前一直想要本身試着實現一個分頁器,可是一直拖,今天寫完,大概照着網易雲音樂的樣子來完成。這個小例子很簡單,經過這個小例子,能夠學習到Vue計算屬性的使用,並瞭解到寫分頁器須要區分的狀況。這篇文章會慢慢從頭來實現這個小例子,相信你必定會學會,並且看完了個人思路以後說不定會有更棒的思路和想法!bash

實現的效果是這樣子的:函數

1、先簡單佈局

<template>
  <div class="pageContainer">
    <ul class="pagesInner">
      <li class="page"><span class="fa fa-chevron-left" aria-hidden="true"></span></li>
      <li class="page" v-for="(item, index) in pages" :key="index">
        <span>{{item}}</span>
      </li>
      <li class="page"><span class="fa fa-chevron-right" aria-hidden="true"></span></li>
    </ul>
  </div>
</template>

<script>
export default {
  computed: {
    pages() {
      return 10;
    }
  }
};
</script>
複製代碼

效果以下:佈局

有兩個地方說下:學習

  • 最前面和最後面兩個icon用的font awesome的cdn
  • 使用v-for來進行渲染的數據用的是計算屬性裏的pages,暫時寫了一個數據11,因此渲染出了11個標籤

2、理清思路,在這個例子裏最重要

這篇文章的例子是參照了網易雲音樂裏的分頁方法,網易的圖:ui

它有幾個特色:this

  • 首頁和尾頁一直都有
  • 最多時候有11個標籤頁,包括兩個 ... ,可是它們不能點擊,因此我也把例子裏的頁碼設爲11
  • 在當前頁變更的時候,頁碼的形態也會發生變化,總共有三種狀況,這個下面會細說

分頁的三種狀況:spa

第一種:當前頁碼小於等於5的時候

如圖:3d

這種狀況首頁尾頁保留,倒數第二個頁面爲..., 頁碼從頭日後算code

第二種狀況:當前頁碼處於最後5個的時候

如圖:cdn

首頁和尾頁依然保留,第二個頁碼爲...,頁碼從最後向前算

第三種狀況:頁面處於較中間位置的時候

如圖:

首頁和尾頁都保留,第二個頁碼和倒數第二個頁碼都爲 ... ,同時頁面從當前頁碼位置向兩側算

3、用代碼來實現上面的三種狀況

從上面的思路來看,頁碼具體如何呈現由當前頁碼的位置決定,因此咱們要在data裏設置一個currentPage:1,而計算屬性裏用於渲染頁碼的pages經過currentPage來控制,同時還須要一個總頁數totalPages:50。

先寫第一種狀況:

<script>
export default {
  data() {
    return {
      currentPage: 1,
      totalPages: 50
    }
  },
  computed: {
    pages() {
      const c = this.currentPage
      const t = this.totalPages
      if (c <= 5) {
        return [1, 2, 3, 4, 5, 6, 7, 8, 9, '...', t]
      }
    }
  }
};
</script>
複製代碼

效果以下:

寫第二種狀況,再加個if:

<script>
export default {
  data() {
    return {
      currentPage: 47,
      totalPages: 50
    }
  },
  computed: {
    pages() {
      const c = this.currentPage
      const t = this.totalPages
      if (c <= 5) {
        return [1, 2, 3, 4, 5, 6, 7, 8, 9, '...', t]
      } else if (c >= t - 4) {
        return [1, '...', t-8, t-7, t-6, t-5, t-4, t-3, t-2, t-1, t]
      }
    }
  }
};
</script>
複製代碼

把currentPage的值設爲>= 46,效果以下:

把第三種狀況加上:

computed: {
    pages() {
      const c = this.currentPage
      const t = this.totalPages
      if (c <= 5) {
        return [1, 2, 3, 4, 5, 6, 7, 8, 9, '...', t]  //第一種狀況
      } else if (c >= t - 4) {
        return [1, '...', t-8, t-7, t-6, t-5, t-4, t-3, t-2, t-1, t] //第二種狀況
      } else {
        return [1, '...', c-3, c-2, c-1, c, c+1, c+2, c+3, '...', t]  //第三種狀況
      }
    }
  }
複製代碼

基本就是這樣,已經能夠經過改變currentPage的值查看分頁器的變化了。

接下來實現點擊相應的頁碼來改變currentPage的值,只要寫一個點擊事件再寫一個函數就行了。

<li class="page" 
    v-for="(item, index) in pages" 
    :key="index"
    :class="{actived: item === currentPage}"   // 給點擊到的當前頁碼添加樣式
    @click="select(item)"     // 添加一個點擊事件
>

...

methods: {
    select(item) {
        this.currentPage = item
    }
}

...

actived: {
    border-color: #2d8cf0;
    background-color: #2d8cf0;
    color: #fff;
}

複製代碼

效果以下:

爲了讓當前頁碼更清楚,再在頁面上加上當前多少頁

<div>當前第{{currentPage}}頁</div>
複製代碼

效果以下:

發現了一bug,就是咱們每次點擊的時候,都是將item的具體內容傳遞過去改變currentIPage的,可是當咱們點的 ... 的時候就把它也傳遞過去了,可是它不是咱們要的頁碼的數據,在計算的時候就出錯了,因此咱們須要作一點處理。同時,還有再點擊當前頁碼的時候也沒必要再執行select函數了。

簡單改寫一下select函數:

select(n) {
    if (n === this.currentPage) return 
    if (typeof n === 'string') return 
    this.currentPage = n
}
複製代碼

這樣就正常了。

再把兩側icon向前一頁和向後一頁的功能加上,由於一個是加1一個是減1,因此寫一個函數傳遞不一樣的參數就好了。

<li class="page" @click="prevOrNext(-1)"><span class="fa fa-chevron-left" aria-hidden="true"></span></li>

...

<li class="page" @click="prevOrNext(1)"><span class="fa fa-chevron-right" aria-hidden="true"></span></li>

...

prevOrNext(n) {
    this.currentPage += n
}
複製代碼

效果以下:

呃,邊界問題,當currentPage爲1時就不能再減了,當它爲最大時也不能再加了。

改寫一下代碼:

prevOrNext (n) {
  this.currentPage += n
  this.currentPage < 1
  ? this.currentPage = 1
  : this.currentPage > this.totalPages
    ? this.currentPage = this.totalPages
    : null
}
複製代碼

這下就能夠了,如圖:

4、 結語

寫到這裏,這個分頁器基本功能就寫完了,固然,咱們還能夠繼續封裝,在每次改變currentPage的時候用this.$emit通知外面實現通訊,還能夠經過props來向內傳遞數據,好比傳遞totalPages等,這些都是能夠繼續完善的內容。最重要的一點,關於分頁器的具體計算方法,我用的是最笨的方法,因此同志們要是知道更好的辦法記得留言啊~

這是我在掘金上的第五篇文章,感謝您的觀看!

相關文章
相關標籤/搜索