天天看點

elementui如何在input 框中搜尋_ElementUI 源碼學習之 Pagination

elementui如何在input 框中搜尋_ElementUI 源碼學習之 Pagination

本文是我學習 ElementUI 源碼的第六篇文章,上一篇文章學習了 ElementUI 中 InfinityScroll 元件的實作,這篇文章來學習一下 ElementUI 是如何實作 Pagination(分頁)元件的。

分頁在網頁中是非常常用的功能,如何制作分頁元件也是前端工程師需要掌握的一個技巧。

元件效果

ElementUI 的分頁元件提供的功能比較豐富,除了正常的翻頁功能外,還提供了跳頁、設定每頁數量、增加自定義元件等功能,效果如下:

elementui如何在input 框中搜尋_ElementUI 源碼學習之 Pagination

pagination

元件實作

首先來看一下分頁元件的項目結構:

elementui如何在input 框中搜尋_ElementUI 源碼學習之 Pagination

struct

其中的

pagination.js

是真正對外提供的分頁元件,它聚合了包括上下頁按鈕、跳頁、總量、每頁數量、頁碼等元件,

pagination.js

是使用

JSX

文法編寫的,好處在于可以少定義很多的判斷變量同時又沒有純

render

函數那麼複雜;而

pager

就是頁碼元件。

pagination 元件

打開

pagination.js

,先看看引入的内容:

Pager

是頁碼元件;

ElSelect

ElOption

用于設定每頁數量;

ElInput

用于實作跳頁;

Locale

是用于實作國際化的,本文不會講解;而

valueEquals

是用于判斷兩個變量是否相等的(針對基本類型和數組),其内容如下:

這段代碼源于 StackOverflow 上的一個回答,ElementUI 對其做了一些優化,感興趣的朋友可以檢視原回答。需要注意的是,這段代碼判斷的數組隻是簡單的一維數組,對于對象數組和多元數組是無效的。

接下來我們開始閱讀

pagination.js

的元件代碼,

props

屬性不需要多講,直接跳到

data

部分,其内容如下:

可以看到,其中定義了四個屬性,

internalCurrentPage

internalPageSize

是元件内部真正使用的目前頁和每頁數量。

在使用分頁元件時,我們會為目前頁(或每頁數量)綁定屬性,而這些屬性值在傳入分頁元件後,是不能直接在分頁元件内容進行修改的,是以分頁元件内部需要維護一份可變屬性。

是以,在

watch

中,ElementUI 定義了更新這兩個屬性的監聽事件:

internalCurrentPage

的監聽是為了實作

.sync

修飾符的同步更新功能。

可以看到

watch

中還有一個對

internalPageCount

的監聽,這個屬性是定義在

computed

中的,它用于計算實際的頁碼總數:

在使用分頁元件時,我們既可以傳入

total

,也可以傳入

pageCount

,甚至同時傳入兩者,為了得到恰當的頁碼總數,ElementUI 定義了

internalPageCount

屬性。

從代碼中我們可以看出,

total

屬性的優先級比

pageCount

高。

lastEmittedPage

userChangePageSize

稍後再講。

接下來我們進入

pagination.js

render

函數,其内容如下:

template

是最終用于渲染的模版,在定義時是最頂級元素,其内容會根據使用者傳入的

layout

屬性從

TEMPLATE_MAP

對象中選出需要使用的子元件,放到

template

children

中,而子元件也是采用

JSX

文法直接寫在

components

中的,後文将重點講解一下

pager

元件,其餘的就不展開了,沒有非常特别的内容(稍微提一下,子元件中大多使用

this.$parent

直接調用的父元件的屬性和方法),感興趣的朋友可以自行檢視。

再往下,我們将目光集中到

rightWrapper

上。

不知道朋友們有沒有發現,

layout

中的書寫順序是會影響分頁元件最終的呈現效果的,其中影響最大的就是

->

,當

layout

中出現此字元串時,處于其後的布局元件将被放入

rightWrapper

中,而它的布局方式是

float:right

elementui如何在input 框中搜尋_ElementUI 源碼學習之 Pagination

rightWrapper

舉個例子:

效果分别是:

elementui如何在input 框中搜尋_ElementUI 源碼學習之 Pagination

layout

接下來我們看看

pagination.js

中的

methods

,其内容如下:

這些方法并沒有太多特别的地方,這裡重點說一下

handleCurrentChange

emitChange

方法,前文遺留的

lastEmittedPage

userChangePageSize

屬性的作用在這裡展現出來了。

handleCurrentChange

方法是傳入到

pager

元件的,用于處理點選頁碼事件,它擷取頁碼的方法是通過

Number(event.target.textContent)

從元素的文本中提取的,而

pager

元件中的點選事件是通過事件委托交給

ul

元素處理的(後文會講)。當點選目前頁碼時,事件也會觸發,是以用

lastEmittedPage

來辨別是否是點選的目前頁碼,以防止觸發

current-change

事件。

userChangePageSize

的作用也是一樣,當使用者修改每頁數量時會造成

pager

元件重新渲染,頁碼更新,是以需要觸發

current-change

事件。

pager 元件

之是以要講一下

pager

元件,主要是因為它對于頁碼的處理過程值得學習一下。

首先看一下元件結構:

關注兩點,第一,頁碼的點選事件都通過事件委托交給了

ul

元素處理,也就是

onPagerClick

,性能更佳;第二,第一頁和最後一頁以及快速跳頁按鈕是直接定義好的了,重點是頁碼如何生成。

我們來看一下

pagers

的代碼:

可以看到

pagers

是一個計算屬性,它會根據

currentPage

pageCount

的值而變化。

不知道有沒有朋友細心觀察過,當分頁元件同時出現前後快速跳頁按鈕時,目前頁碼永遠處于最中間,而且通過

pagers

生成的頁碼數量為

pager-count

設定的值減去 2,因為第一頁和最後一頁是直接定義好了的。

elementui如何在input 框中搜尋_ElementUI 源碼學習之 Pagination

pager

根據 ElementUI 的約定,

pager-count

的取值範圍為 5 - 21 之間的奇數,這樣能讓分頁元件有統一的良好的視覺效果。

頁碼的生成邏輯就是上述代碼中的

if

語句,感興趣的朋友可以仔細研究一下 ElementUI 是如何進行判斷的,并不複雜。

處理頁碼點選事件的函數

onPagerClick

内容比較簡單,就不再展開了,感興趣的朋友可以自行查閱。

結語

通過學習分頁元件的源碼,我們可以發現一個長期以來開發者争論的問題,即模闆文法好還是

JSX

好,其實兩者各有優勢,有各自适用的場景。就如同

pagination.js

中選取子元件的邏輯部分,如果用模闆文法的話會在 HTML 中增加很多的

v-if

,閱讀起來很不友善。

首圖由InspiredImages在Pixabay上釋出