簡單封裝分頁功能pageView.js

来源:http://www.cnblogs.com/lyzg/archive/2016/08/21/5791011.html
-Advertisement-
Play Games

分頁是一個很簡單,通用的功能。作為一個有經驗的前端開發人員,有義務把代碼中類似這樣公共的基礎性的東西抽象出來,一來是改善代碼的整體質量,更重要的是為了將來做類似的功能或者類似的項目,能減少不必要的重覆工作量。在實際項目中,尤其是網站類型的項目中,分頁部分的設計總是個性化比較強,基本上都不會長的一樣, ...


分頁是一個很簡單,通用的功能。作為一個有經驗的前端開發人員,有義務把代碼中類似這樣公共的基礎性的東西抽象出來,一來是改善代碼的整體質量,更重要的是為了將來做類似的功能或者類似的項目,能減少不必要的重覆工作量。在實際項目中,尤其是網站類型的項目中,分頁部分的設計總是個性化比較強,基本上都不會長的一樣,所以可能之前抽象出來的東西,如果寫的不夠靈活的話,對這些個性化強的項目來說,可能直接應用的時候也得做些調整才行。本文嘗試提供一個儘量滿足這兩方面要求的分頁組件。

先介紹下寫這個東西的背景:一直以來,我都想寫一個相對比較靈活簡單的列表組件,去年寫過一個版本,後來改了幾次,現在已經用到好幾個項目裡面去了,重構起來也有不少的工作量,因為應用到的頁面已經把比較多了,所以就沒有輕易地去做這個事情。最近的工作,涉及到一個相對簡單的列表頁面,然後給的時間也比較多,於是我準備趁這個時候把我一直想寫的列表組件給寫出來。現有的那個列表管理組件,沒有做好職責分離,列表的管理跟分頁的管理是揉在一起的,代碼也比較亂,所以這次我打算先從分頁組件下手。因為分頁組件與列表之間並沒有太多耦合的邏輯,所以當把它們分離出來的時候,代碼會更加清晰,獨立,將來要維護也方便些。前端雖然做不到像後臺那樣,考慮那麼多的設計模式,但要是能把代碼寫的更讓人容易理解的話,對團隊對公司來說,真的是一件很好的事情。

雖然網上有不少的分頁插件,但是都不值得去用,一來是有輕微的學習成本,二來是不符合自己的封裝的思想,看著彆扭;而且像這樣簡單的封裝,最適合自己動手去寫,加強面向對象編程的鍛煉了。

下麵就開始這個分頁組件的內容。

基本思想

先來說下我的基本想法。分頁這個部分,從內容上可能包括有:上一頁,首頁,下一頁,尾頁以及具體頁;頁碼輸入跳轉;分頁大小;記錄總數;記錄範圍等;從結構上,必須知道分頁大小,當前頁的索引以及記錄總數才能構造所有的內容;從操作上:改變分頁大小,或者是點擊上一頁,首頁,下一頁,尾頁以及具體頁,或者是直接輸入頁碼,都會引發外部分頁內容的拉取。對外部來說,不管分頁部分做什麼操作,只要在這些操作之後,通知外部去拉取即可,分頁只需要提供一個簡單的api給外部,告訴它們當前的分頁大小和頁碼;但是在外部拉取到新的內容之後,還得做一件事情,就是要根據最新的記錄總數,去更新分頁部分的UI,前面說分頁的內容需要記錄總數,頁碼和分頁大小才能構造出來。由於頁碼跟分頁大小都屬於分頁內部管理的,所以外部更新分頁UI的時候,只需要告訴分頁最新的記錄數就夠了。以上就是分頁組件跟外部功能互相交互時候的唯一場景,基於這些,就可以把所以把分頁相關的東西都封裝起來,給外部提供幾個簡單的api來實現它們之間的調用關係,最終完成我們需要的分離的目的。

效果演示

方便大家看到這個東西的實際用法跟效果,我模擬真實的場景,寫了一個簡單的demo,一起來看看。

demo效果:

image

demo地址:

http://liuyunzhuge.github.io/blog/form/dist/html/pageView.html

pageView相關css:

https://github.com/liuyunzhuge/blog/blob/master/form/src/css/page_view.css

pageView.js源碼:

https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/pageView.js

demo相關的源碼:

https://github.com/liuyunzhuge/blog/blob/master/form/src/js/app/pageView.js

源碼部分也可以直接打開demo地址,通過chrome的開發者工具來查看,因為這些代碼放在git上面,是跟我以前的代碼放在一塊的,怕不知道的人還以為這麼個小東西,還需要寫那麼多個文件。再補充下其它方面的說明:這些代碼都是用seajs管理的,然後整個pageView.js是用我自己之前寫的一個用來做js的面向對象編程的模塊class.js方式開發的,可能沒瞭解過的人,不知道它是做什麼用,關於它的介紹都在下麵這篇文章裡面:

詳解Javascript的繼承實現

DEMO解析

直接看我在demo里,完成那個頁面的核心代碼:

無標題

從上面的代碼也能看出,這個分頁組件最核心的api也就是下麵幾個:

getParams():它是一個實例方法,返回組件的分頁大小跟頁碼,至於這兩個值的參數名字,可以通過option來修改;

refresh(total):這也是一個實例方法,外部傳給它一個最新的記錄總數,分頁組件再根據它重新渲染UI;

onChange:這是一個函數類型的回調,它可以作為一個option在創建實例的時候傳入,所有分頁操作都會反饋到這個回調裡面來,通常只要把外部拉取內容的動作綁定它上面即可。

考慮到要控制分頁的重覆操作問題,還另外加了一個disable和enable的api,這個比較好理解了。當分頁被disable的時候,會顯示禁用的樣式,cursor為not-allowed,所有分頁操作都將無效。

實際上,我在最近的一個項目中, 寫類似demo的一個簡單分頁功能,就是這麼寫的,業務代碼很少,邏輯也比較清晰,雖然說列表管理,比如渲染那一塊,還可以再封裝一下,但是在這種簡單場景中,不再去封裝,也是可以的,因為它本身已經很簡單,再想辦法封裝,也增加不了多少的靈活性。

現在還有不少的公司在採用沒有封裝的代碼,分頁的功能在不同的頁面都寫一遍,每個位置都定義五六個function,比如goFirst goPrev goLast goNext goPage這種,從結果上來說沒啥不好,就是在做重覆的事情的時候效率不高,不好維護。要是都能封裝起來,相信能給團隊帶來不少好處。

概要說明

先從option說起,以下是pageView.js定義的所有option及預設值:

var DEFAULTS = {
    defaultIndex: 1,//預設頁
    defaultSize: 10,//預設分頁大小
    pageIndexName: 'page',//分頁參數名稱
    pageSizeName: 'page_size',//分頁大小參數名稱
    onChange: $.noop,//分頁改變或分頁大小改變時的回調
    onInit: $.noop,//初始化完畢的回調
    allowActiveClick: true,//控制當前頁是否允許重覆點擊刷新
    middlePageItems: 4,//中間連續部分顯示的分頁項
    frontPageItems: 3,//分頁起始部分最多顯示3個分頁項,否則就會出現省略分頁項
    backPageItems: 2,//分頁結束部分最多顯示2個分頁項,否則就會出現省略分頁項
    ellipseText: '...',//中間省略部分的文本
    prevText: '上一頁',
    nextText: '下一頁',
    prevDisplay: true,//是否顯示上一頁按鈕
    nextDisplay: true,//是否顯示下一頁按鈕
    firstText: '首頁',
    lastText: '尾頁',
    firstDisplay: false,//是否顯示首頁按鈕
    lastDisplay: false,//是否顯示尾頁按鈕
};

我把其中需要再詳細解釋下的說明清楚。

1)pageIndexName和pageSizeName

這兩個用來定義分頁參數的名字,還記得那個getParams方法嗎,它是這樣的:

image

getParams返回一個對象,這個對象包含兩個鍵值對,鍵分別用pageIndexName和pageSizeName這兩個option,值就用分頁內部管理的分頁大小和頁碼。當外部調用這個方法時,就能直接把它的返回值作為查詢參數傳遞到後臺介面了。

2) middlePageItems,frontPageItems,endPageItems

也許看了demo裡面的分頁部分的效果就能明白它們三個的作用:

image

middlePageItems代表中間連續部分的分頁項的數量;

frontPageItems代表起始部分連續的分頁項的數量;

endPageItems代表結尾部分連續的分頁項的數量。

這三個option之所以要定義,是由當前這個分頁組件要做的效果,以及它使用的分頁演算法決定的。

然後pageView定義的實例方法就不過多說明瞭,因為都比較簡單,而且最核心的都已經在demo裡面體現出來,感興趣的話,照著用即可。如果對代碼感興趣,碰到有疑問的,歡迎私信一起交流。

最後說下分頁演算法。影響分頁組件能不能通用的另外一個要素就是分頁演算法。有的可能不需要分頁演算法,直接從1到總頁數顯示出來就完了,但是這樣肯定有問題,尤其當總頁數很多的時候;有的分頁跟我這個就不太一樣,它可能只顯示當前頁在內的連續一部分頁碼,然後當切換不同的頁的時候,這個連續部分也不相同;我這裡用的是較為常見的一個演算法,首尾以及中間都有連續部分。詳細的渲染邏輯都在render方法裡面,但是最核心的東西其實還是getInterval這個函數:

function getInterval(data, opts) {
    var ne_half = Math.ceil(opts.middlePageItems / 2);
    var np = data.pages;
    var upper_limit = np - opts.middlePageItems;
    var start = data.pageIndex > ne_half ? Math.max(Math.min(data.pageIndex - ne_half, upper_limit), 0) : 0;
    var end = data.pageIndex > ne_half ? Math.min(data.pageIndex + ne_half, np) : Math.min(opts.middlePageItems, np);
    return [start, end];
}

它的作用在於返回中間連續部分的起止索引。根據這個起止索引渲染中間部分的頁碼,然後把start和frontPagetItems比較,渲染起始部分的頁碼;把end與與backPageItems比較,繪製結尾部分的頁碼。

其它問題

以上就算是這個分頁組件的全部核心內容了。但是最終來看,它還是有些問題的。一開始我就說過,這種東西要是能做到足夠靈活,能夠滿足不同項目裡面相同功能的話,這樣就才算強大。基於這點來看目前的pageView,它的問題在於:

1)固化了分頁演算法,要是換一個項目,產品不想搞這個分成首尾中間連續三部分的效果,那麼就必須改動源碼才能適應需求了。要解決這個問題,可以考慮把pageView再抽象出一個父類,不同的子類去覆蓋render方法,也就是在項目中提供多個pageView的實現,要用哪個,根據需求來定。

2)沒有包括分頁大小,頁碼跳轉,記錄總數和記錄範圍這些內容,有可能其他項目需要這些東西,作為分頁的輔助功能。要解決這個問題,可以考慮在當前的版本上擴充,補充事件的監聽,添加一些合適的option,控制這些內容是否顯示即可。

我之所以沒有去解決上面的這些問題,有兩個原因:

1)就目前的所有場景來說,沒有碰到要額外內容的場景,如分頁大小等,所以先不處理,避免增加這個組件的複雜性;

2)對於分頁演算法,我認為在產品設計中沒有必要做出太多的不同的設計出來,所以固化一種沒有問題。因為不管從哪一方面,為不同的頁面提供不同的分頁演算法都是一件很划不來的事情,如果當產品出現這種問題的時候,我會儘力去把他說服。

當然,每個人想法不同,堅持自己的思想最好。

最後希望本文多少對大家有點用處,謝謝閱讀:)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、通過class獲取標簽 var out=document.getElementsByClassName(‘out’);IE 6 7 8 不支持 getElementsName 是否有辦法既能通過class獲取標簽又沒有相容問題 ? 首先獲取全部的標簽, 用for迴圈遍歷到所有類名相同的標簽, 遍 ...
  • 1.首先肯定是要安裝Node.JS windows cmd依次輸入如下命令: cd C:\Program Files\nodejs\ npm install -g expressnpm install -g express-generator 2.創建一個示例工程 windows cmd依次輸入如下 ...
  • 在看此課程的讀者,希望先閱讀關於函數基礎內容 函數定義與函數作用域 的章節,因為此課程或多或少會涉及函數基礎的內容,而基礎內容,本人放在 函數定義函數作用域 章節。 本文直接贅述函數參數與閉包,若涉及相關知識,為了節省篇章,會以相關字眼帶過。 最近在學習javascript的函數,函數是javasc ...
  • <html> <head> <title>表格內容的篩選</title> <link type="text/css" rel="stylesheet" href="css/contains.css" /> <style type="text/css">table { width: 50%; bord ...
  • 0.什麼是標記 這裡的checked、id、href、title就是標記 1.布爾標記 已checked為例 存在即應用,用來標記狀態, 如果存在改標記,getAttribute的值始終使checked,不存在getAttribute的值是undefined, 通過setAttribute、remo ...
  • 在文檔載入之後使用 document.write(),會覆蓋該文檔。 需滿足兩個條件: 1、在函數內部調用document.write(); 2、通過按鈕響應調用函數; 舉例: 輸出結果: 點擊“點擊這裡”,載入文檔,文檔被覆蓋: 輸出結果: 點擊“點擊這裡”,載入文檔,文檔被覆蓋: ...
  • iframe作為一個網站之間交互的橋梁,受到很多站長的喜愛,但是又有不安全的因素存在,所以正確填寫屬性是很重要的。 <iframe name="my_iframe" height="540" width="100%" frameborder="0" marginwidth="0" marginhei ...
  • 推薦10款最熱門jQuery UI框架 原創 推薦10款最熱門jQuery UI框架 原創 在進行Web開發時,並非所有的庫都適合你的項目,但你仍需要收藏一些Web UI設計相關的庫或框架,以在你需要的時候,加快你的開發效率。本文為你推薦10款非常優秀的基於JQuery的Web UI設計框架 在進行 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...