QingUI是一個UI組件庫
目前擁有的組件:DatePicker, TimePicker, Paginator, Tree, Cascader, Checkbox, Radio, Switch, InputNumber, Input
ES6語法編寫,無依賴
原生模塊化,Chrome63以上支持,請開啓靜態服務器預覽效果, 靜態服務器傳送門
採用CSS變量配置樣式
辛苦造輪子,歡迎來github倉庫star: https://github.com/veedrin/qing
四月份找工做,求內推,座標深圳
去年年末項目中嘗試着寫過一個分頁的Angular組件,而後就有了寫QingUI的想法javascript
過程仍是很是有意思的前端
接下來我會用幾篇文章分別介紹每一個組件的大概思路,請你們耐心等待java
這一篇介紹Paginator分頁git
最重要的,求star,求fork,求內推github
repo: QingUI
通常的需求是,我有一個列表,可是我不想一下讓用戶看這麼多,一次看一點,再想看,翻到下一頁後端
固然如今有無限滾動,只要滾動到必定距離,就給你加載新的數據,這個咱們不考慮數組
分頁也有兩種作法,一種是一次性加載全部數據,前端作分頁;一種是每次加載一部分,點擊分頁就是觸發再次加載的動做服務器
第一種作法應該不多見了吧,首次加載的壓力太大模塊化
頁面初始加載的時候向後臺請求數據,請求哪些數據呢?要顯示的列表信息,還有當前是第幾頁函數
若是每頁顯示多少條是可配置的,那麼還須要每頁顯示多少條和總條數
初始加載確定是第一頁
而後用戶看完第一頁,往下翻,多是翻到第二頁,也多是翻到後面的任一頁,無所謂
咱們獲取到用戶想翻到第幾頁的信息之後,傳給後端,後端再把相應頁的列表信息傳過來,前端展現
注意,這個時候分頁是要變的,用戶點擊的那一頁要高亮,以前那一頁去掉高亮,若是頁數比較多,省略號的位置也要根據規則發生變化
因此咱們得出一個重要信息,分頁組件展現頁碼的那一塊每次點擊都是要從新渲染的
$bar
就是展現頁碼的容器,展現頁碼的模板封裝到另外一個函數裏
一開始能想到這個,後面就不須要推倒重來了,你猜我有沒有推倒重來 :)
tpl += ` <div class="square end prev">﹤</div> <div class="bar"></div> <div class="square end next">﹥</div> `;
若是咱們把展現邏輯放到模板渲染函數裏,那模板渲染函數會變得很是繁雜
咱們能夠分紅兩步,第一步構建數據模型,第二步根據數據模型生成模板
我仔細的觀察過GitHub(GitHub已經很是優美了)的分頁邏輯,QingUI的分頁邏輯就是根據GitHub來的
我總結了一下,代碼註釋裏也有:
哦,忘了解釋,數據模型是怎麼映射的
分頁都是從1開始,最大隨意(通常不會太大),因此咱們構建一個數組,1到正無窮就表明1到正無窮頁,0表明省略號
1到7頁之間能夠徹底展現,爲何?
首尾各1頁,中間共5頁,加起來就是7頁,超過7頁就會有省略號
不是說跨度大於等於2頁纔會有省略號嗎?
由於首頁和中間的5頁是能夠重合的,若是有8頁,前面5頁和最後1頁中間正好隔了2頁
因此1到7頁之間能夠徹底展現
for (let i = 1; i <= c; i++) { this.model.push(i); }
若是當前頁小於4,至少要保證當前頁加左右至少有5頁,因此這種狀況要單獨拎出來
後面再加一個省略號,以及尾頁
for (let i = 1; i <= 5; i++) { this.model.push(i); } this.model.push(0, c);
這種狀況就是首頁和中間5頁不重合的狀況,因此for循環不須要寫死
一樣,後面再加一個省略號,以及尾頁
for (let i = 1; i <= p + 2; i++) { this.model.push(i); } this.model.push(0, c);
這種狀況就是距離首頁的跨度大於等於2,距離尾頁的跨度也大於等於2,因而先後都有省略號
this.model.push(1, 0); for (let i = p - 2; i <= p + 2; i++) { this.model.push(i); } this.model.push(0, c);
這種狀況是說後面沒有省略號了,可是也不至於和尾頁產生重合
this.model.push(1, 0); for (let i = p - 2; i <= c; i++) { this.model.push(i); }
中間5頁與尾頁產生重合了,至少要保證渲染出5頁,因此for循環寫死
this.model.push(1, 0); for (let i = c - 4; i <= c; i++) { this.model.push(i); }
6種狀況:
仍是挺有規律的是吧
數據模型代碼
buildModel() { // 每次從新初始化 this.model = []; const c = this.pageCount, p = this.position; if (c < 8) { for (let i = 1; i <= c; i++) { this.model.push(i); } } else { if (p < 4) { for (let i = 1; i <= 5; i++) { this.model.push(i); } this.model.push(0, c); } else if (p < 6) { for (let i = 1; i <= p + 2; i++) { this.model.push(i); } this.model.push(0, c); } else { if (p < c - 4) { this.model.push(1, 0); for (let i = p - 2; i <= p + 2; i++) { this.model.push(i); } this.model.push(0, c); } else if (p < c - 1) { this.model.push(1, 0); for (let i = p - 2; i <= c; i++) { this.model.push(i); } } else { this.model.push(1, 0); for (let i = c - 4; i <= c; i++) { this.model.push(i); } } } } }
若是你不喜歡GitHub分頁規則,或者本身有特殊的需求
能夠根據上面的規律本身定製一套分頁邏輯
真的,往上套就能夠了
數據模型都構建出來了,渲染就簡單了
for (const item of this.model) { if (item > 0) { if (this.position !== item) { tpl += `<div class="square page">${item}</div>`; } else { tpl += `<div class="square page active">${item}</div>`; } } else { tpl += '<div class="square gap">···</div>'; } }
在某些狀況,咱們要讓用戶知道往前或者日後點擊是無效的,要進行置灰處理
規則也挺簡單的
if (this.position === 1) { this.$prev.classList.add('disabled'); this.$next.classList.remove('disabled'); }
if (this.position === this.pageCount) { this.$next.classList.add('disabled'); this.$prev.classList.remove('disabled'); }
if (this.position === this.pageCount) { this.$prev.classList.remove('disabled'); this.$next.classList.remove('disabled'); }
這種狀況很容易被忽略
若是總共只有1頁,那左右都點不了,並且當即返回
if (this.pageCount === 1) { this.$prev.classList.add('disabled'); this.$next.classList.add('disabled'); return; }
這裏主要是注意一個問題
假如如今的當前頁是比較靠後的位置
而後我增長每頁顯示的條數,那勢必總頁數就變小了
有可能總頁數變的比當前頁還小
那麼這個時候就只能強制改變當前頁,讓它變成最後1頁了
這就是一個輸入框,加keyup監聽Enter
鍵的事件
Paginator比較核心的邏輯就在這裏了
最有意思的是構建數據模型的那一段,挺費腦子的
下一篇文章介紹Tree,敬請期待
最後,求star,求fork,求內推
repo: QingUI