列表元件抽象(2):listViewBase說明

發表於2016-09-19

listViewBase是列表元件所有檔案中最核心的一個,它抽象了所有列表的公共邏輯,將來如果有必要新增其它公共的邏輯,都可以考慮在這個類中處理。它主要做的事情包括:初始化,如排序元件初始化,分頁元件初始化,模板管理引擎初始化,事件繫結和請求傳送及處理等。這個檔案看起來比較長,有300度行,但是非常好理解。下面我會把它的每個要點內容一一說明。

原始碼地址:https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/listView/base/listViewBase.js

首先看看程式碼的整體結構。

459873-20160918162608868-1779307793

注:程式碼中的EventBase是我原來寫的一個元件,基於jquery,簡單實現任意物件支援事件管理的功能【jquery技巧之讓任何元件都支援類似DOM的事件管理】;Class也是我原來寫的一個元件,用來支援物件導向思想的類的構造&繼承【詳解Javascript的繼承實現】;Ajax也是一個簡單的元件,對jquery的ajax進行了二次封裝,以便ajax請求的管理更符合自己的思維習慣【對jquery的ajax進行二次封裝以及ajax快取代理元件:AjaxCache】。

listViewBase的整體結構跟我以前的寫的元件基本一致,畢竟已經養成這個習慣了。DEFAULTS表示元件的預設options,它繼承了EventBase來實現自身的事件管理。在元件類的靜態成員上,繫結了DEFAULTS,是為了方便子類進行引用;定義了一個dataAttr的屬性,它有兩個作用:第一是作為data屬性,在將元件例項繫結到相關DOM元素的jq物件上時用到:

459873-20160918162610086-1984157948

第二是用於生成元件的事件名稱空間,元件內所有的事件都會加上這個事件名稱空間,以便不會產生事件衝突:

459873-20160918162612102-1646723888
459873-20160918162613274-489055787

接著看看DEFAULTS的定義,我會挑主要的進行解釋:

其中:

1)isAjaxResSuccess , getRowsFromAjax , getTotalFromAjax作用跟ajax的返回解析有關。通常做了自定義的ajax返回封裝後,ajax的返回可能是類似這樣的:

以上這個ajax返回demo模擬了一個分頁列表時某次ajax請求返回的資料,其中code屬性為200表示這個ajax是成功的,ajax返回的資料集合存放在data.rows屬性上,資料的總記錄數存放在data.total屬性上。有可能你的專案中,分頁列表返回的資料結構跟這個不一樣,但是對於列表元件來說,有三個要素是一個請求的返回中必須包含的:

a. 什麼樣的返回才是成功的;

b. 返回中的哪一部分表示當前請求的資料集;

b. 返回中的哪一部分表示當前資料型別的記錄總數。

isAjaxResSuccess , getRowsFromAjax , getTotalFromAjax解決的就是這三個問題。我提供的這三個option的預設值都是按前面的那個json結構寫的,如果你的專案中列表ajax請求不是這個json結構,只要改變這三個option的定義即可。

2)parseData和renderParse用於解析getRowsFromAjax返回的資料,以及為模板引擎提供它所需要的model物件。在一個列表ajax請求中,很有可能某些返回的資料不適合直接顯示在頁面裡面,比如時間戳格式的欄位,我們可能更需要把它轉化為我們所習慣的日期格式字串才行,這個時候只要利用parseData方法即可,這個方法接受getRowsFromAjax返回的資料作為唯一的引數。renderParse跟模板引擎有關係,拿mustache來說,如果我定義tpl的時候用的是下面類似的結構:


意味著我在使用mustche渲染的時候,需要傳入一個{rows: …}的model才行,這個model裡面的rows是根據tpl裡面的{{#row}}來確定的。預設情況下,我在定義tpl的時候,都使用rows作為遍歷屬性名,如果你不習慣用rows,那麼可通過renderParse這個option來自定義要使用的遍歷屬性名。比如換成records:

3)afterInit等事件的作用在於元件例項可根據自身的需求場景,在這些事件派發的時候,新增額外的一些處理邏輯,而不會影響別的例項。

4)pageView跟sortView用來傳遞分頁元件和排序元件例項化的時候,要傳入的options。如果為false,則表示這個列表元件沒有對應的分頁元件或排序元件。

5)queryDelay如果大於0,那麼就會延遲傳送ajax請求,延遲時間就等於queryDelay設定的時間。

接下來看看一些關鍵的例項方法定義。

1)init方法

原始碼:

這個方法其實很簡單,就是按順序做一些初始化的邏輯而已。稍微值的一提的是,為了讓子類支援更靈活的擴充套件,這個方法在一些關鍵程式碼的前後都加了空方法,以便子類在父類的這些關鍵程式碼執行前後,插入自己的邏輯。createPageView用於子類返回分頁元件的例項,如果返回了分頁元件例項,會自動監聽分頁元件的相關change事件,並呼叫列表元件的refresh方法,以便根據最新的分頁引數重新整理列表。createSortView用於子類返回排序元件的例項,作用完全類似createPageView。

2. bindEvents方法

就是註冊事件而已。不過子類在提供自己的bindEvents方法的時候,必須在它的bindEvents,通過this.base()呼叫父類的bindEvents方法。這裡沒有像init方法那樣,增加很多空方法來處理。畢竟沒有那麼多個性化的位置。

3. getParams方法

返回列表的引數:

在請求傳送時,會呼叫這個方法來獲取要傳遞給後臺的引數。

4. renderData方法

子類不用實現,但是子類會用到,它在內部呼叫模板引擎管理元件,來返回渲染之後的html字串,子類在拿到這個字串之後,可做DOM更新的操作。

5. refresh方法

代表列表重新整理。僅在分頁或排序改變的時候呼叫。

6. query方法

代表列表查詢。這個方法跟refresh方法都在內部呼叫_query函式進行請求的處理,但是兩個方法使用的場景不一樣。

refresh方法基本上不影響引數,如果是分頁refresh,那麼引數中只有分頁引數會變化;如果是排序refresh,那麼引數中只有排序引數會變化;如果是其它refresh,所有引數都不變化,列表只是按當前條件重新請求一遍資料而已。

query方法不一樣:它接收新的查詢條件,用於更新原來的查詢條件。並且它會重置分頁排序元件,如果resetSortWhenQuery為true,它還會重置排序元件。query方法可以實現比較強大的列表查詢功能。下面我會盡量詳細介紹它的用法,由於沒有查詢條件的表單,所以我直接在控制檯模擬一下了。你可以直接用http://liuyunzhuge.github.io/blog/form/dist/html/tableView.html這個頁面進行操作,我把這個頁面裡面的的列表元件例項已經存放在window.l屬性上,所以在控制檯可以通過l這個全域性變數拿到列表元件例項。

在此之前,我先假設有一個列表頁面,放了兩個查詢條件,一個是按型別查,一個是按關鍵詞查,當我們要執行搜尋的時候,可以用下面的方式在給列表增加查詢條件:

檢視ajax請求,可以看到新新增的請求引數:


如果此時改變其中一個查詢條件的值:

列表就會用新的查詢條件請求資料:


如果在改變查詢條件的同時,給query方法傳遞第二個引數,值為false:

會發現這次的列表請求中,已經沒有了之前的那個keywords的引數:


因為query方法的第二個引數如果是false的話,列表元件在更新查詢條件的時候,將採用替換而不是覆蓋的方式處理。

前面說的query方法會重置分頁元件或排序元件,是指在請求前會呼叫分頁元件或排序元件例項的reset方法,以便還原排序和分頁引數值為預設值。

最後再看核心一個函式定義:_query函式。

這個函式原始碼較長,但是理解起來應該不會麻煩,因為它也跟init方法一樣,純粹是按順序編寫的一些邏輯。在這個函式裡面呼叫了另外幾個模板方法,派發了大量的事件。雖然看起來這些模板方法,跟事件的作用有些重合,其實它們的作用是完全不同的。模板方法是直接新增在類層面的,它可以為子類提供類級的擴充套件;而事件是由具體的例項派發的,所以它只能在給特定的例項新增擴充套件。

這些模板方法以及事件的觸發順序也比較關鍵,都是按照先呼叫模板方法,再派發事件的順序來的,拿querySuccess方法與success事件來說,一定是先呼叫querySuccess方法,再派發success事件,這個原由也跟前面的類級擴充套件和例項級擴充套件的層次有關係。所有模板方法以及事件的呼叫關係,按照請求成功或失敗分了2條線,我在註釋中已經描述地很清楚了。

以上就是listViewBase這個基類的全部內容了。

接下來看看它的子類該如何實現,以simpleListView為例:


忽略掉SimplePageView以及SimpleSortView的實現,這個我下一篇部落格會補充說明,你會發現實現一個簡單的列表元件已經非常簡潔了,程式碼不到70行。

下一篇部落格補充對排序跟分頁元件的說明。

相關文章