之前一直想要自己試著實現一個分頁器,但是一直拖,今天寫完,大概照著網易雲音樂的樣子來完成。這個小例子很簡單,通過這個小例子,可以學習到Vue計算屬性的使用,並瞭解到寫分頁器需要區分的情況。這篇文章會慢慢從頭來實現這個小例子,相信你一定會學會,而且看完了我的思路之後說不定會有更棒的思路和想法!
實現的效果是這樣子的:
一、先簡單佈局
<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個標籤
二、理清思路,在這個例子裡最重要
這篇文章的例子是參照了網易雲音樂裡的分頁方法,網易的圖:
它有幾個特點:
- 首頁和尾頁一直都有
- 最多時候有11個標籤頁,包括兩個 ... ,但是它們不能點選,所以我也把例子裡的頁碼設為11
- 在當前頁變動的時候,頁碼的形態也會發生變化,總共有三種情況,這個下面會細說
分頁的三種情況:
第一種:當前頁碼小於等於5的時候
如圖:
這種情況首頁尾頁保留,倒數第二個頁面為..., 頁碼從頭往後算
第二種情況:當前頁碼處於最後5個的時候
如圖:
首頁和尾頁依然保留,第二個頁碼為...,頁碼從最後向前算
第三種情況:頁面處於較中間位置的時候
如圖:
首頁和尾頁都保留,第二個頁碼和倒數第二個頁碼都為 ... ,同時頁面從當前頁碼位置向兩側算
三、用程式碼來實現上面的三種情況
從上面的思路來看,頁碼具體如何呈現由當前頁碼的位置決定,所以我們要在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
}
複製程式碼
這下就可以了,如圖:
四、 結語
寫到這裡,這個分頁器基本功能就寫完了,當然,我們還可以繼續封裝,在每次改變currentPage的時候用this.$emit
通知外面實現通訊,還可以通過props
來向內傳遞資料,比如傳遞totalPages等,這些都是可以繼續完善的內容。最重要的一點,關於分頁器的具體計算方法,我用的是最笨的方法,所以同志們要是知道更好的辦法記得留言啊~
這是我在掘金上的第五篇文章,感謝您的觀看!