JavaScript 組件之旅(一)分析和設(shè)計
這次,我們將以一個簡易的 JavaScript 組件開發(fā)為契機(jī),逐步展開組件的分析、設(shè)計、實(shí)現(xiàn)、構(gòu)建和測試等任務(wù),探討組件開發(fā)過程涉及的方方面面。這些探討將分 4 篇陸續(xù)張貼出來(鏈接將在張貼后更新):
- 分析和設(shè)計組件
- 編碼實(shí)現(xiàn)和算法
- 用 Ant 構(gòu)建組件
- 測試 JavaScript 組件
現(xiàn)在,假設(shè)我們要從頭開始設(shè)計并實(shí)現(xiàn)一個隊(duì)列管理組件,先讓我們來認(rèn)識一下隊(duì)列:
Queue
圖片來自 Wikipedia.
隊(duì)列是一個“先進(jìn)先出”(FIFO) 的數(shù)據(jù)結(jié)構(gòu),只能向它的尾巴追加項(xiàng),項(xiàng)從頭部取出使用,這個規(guī)則將應(yīng)用到我們所探討的組件中去。對于隊(duì)列,相信學(xué)過 C 或是數(shù)據(jù)結(jié)構(gòu)課程的同學(xué)已有所了解,如果你已經(jīng)把它還給了老師,請使用搜索引擎簡單了解一下隊(duì)列的知識。
這個隊(duì)列管理組件具體要實(shí)現(xiàn)的功能是:它是個任務(wù)管理器,按高、中、低優(yōu)先級維護(hù)著三個任務(wù)隊(duì)列,客戶(使用者)可以在任何時候把想要執(zhí)行的任務(wù)添加到某個隊(duì)列,可以指定任務(wù)運(yùn)行的上下文,并傳給它必要的數(shù)據(jù)??蛻粢部梢噪S時運(yùn)行這個隊(duì)列,隊(duì)列里的任務(wù)按照指定的依賴關(guān)系以合理的方式依次運(yùn)行。
為了不至于使組件過于簡單而缺乏實(shí)用性,我們特意給它添加了一些“糖”:分優(yōu)先級、傳入上下文和數(shù)據(jù)、處理依賴關(guān)系。如果把上面這段理解為需求的話,那么首先,我們要從中提取出最重要的關(guān)鍵詞,它們直接決定了這個組件應(yīng)該如何設(shè)計:
- 隊(duì)列
- 優(yōu)先級
- 依賴關(guān)系
然后,我們從中提煉出涉及的對象:
- 任務(wù)管理器 (TaskManager): 從目前需求來看,它只需要一個實(shí)例。
- 隊(duì)列 (Queue): 每個優(yōu)先級對應(yīng)一個隊(duì)列,由
TaskManager管理這三個Queue實(shí)例。 - 任務(wù) (Task): 描述添加的任務(wù),放在相應(yīng)優(yōu)先級的
Queue里面。 - 依賴 (Dependency): 描述單一的依賴,即
Task1依賴Task2, 顯然某個Task可能具有多個依賴。
它的對象模型可以大概表示如下:
設(shè)計初期的對象圖
注意到 Dependency 實(shí)際上并沒有做什么事,而 Queue 的兩個方法可以分別交給 TaskManager & Task 來負(fù)責(zé)。一個方法到底由哪個對象負(fù)責(zé),是很容易引起爭論的話題,不在我們的討論范圍內(nèi)。這次,我們的重點(diǎn)是,采用 JavaScript 實(shí)現(xiàn)這個組件,結(jié)合 JavaScript 獨(dú)特的語言特性,我們設(shè)想實(shí)現(xiàn)上述四個對象:
TaskManager直接通過對象 (Object) 實(shí)現(xiàn)。在 JavaScript 的世界,對象可以作為天然的靜態(tài)類來使用——你可以直接在“類”ClassObject里面定義屬性方法property,并以靜態(tài)類的方式來引用CassObject.property.Queue以數(shù)組 (Array) 的形式體現(xiàn)出來,Task則是數(shù)組中存放的每一項(xiàng)。對Queue進(jìn)行操作必然要在其 prototype 中定義一些實(shí)例方法,由于每個 Queue 實(shí)例都是原生的數(shù)組,為了減少對Array.prototype的侵入,我們可以考慮將這些方法定義到Task.prototype上——將職責(zé)轉(zhuǎn)移到任務(wù)上。
將三個Queue數(shù)組集結(jié)在一起,形成一個“大數(shù)組”以表示三個不同優(yōu)先級的隊(duì)列,這個大數(shù)組可以作為TaskManager的屬性。- 任務(wù)的核心是一個 function, 本來可以直接用 function 來表示一個任務(wù),但考慮到它具有自身獨(dú)特的屬性(優(yōu)先級、依賴等等),而且是最經(jīng)常被操作的對象,以后可能還會進(jìn)行擴(kuò)展,所以我們決定單獨(dú)將其定義成對象。
- 依賴直接以數(shù)組的形式作為
Task的一個屬性存在——Task將依賴的其他多個Task標(biāo)識符放在這個數(shù)組中,不再單獨(dú)定義這個對象。
分析下來,局勢逐漸明朗——我們需要將四個對象簡化成兩個:TaskManager & Task, 另外兩個對象用原生的數(shù)組來實(shí)現(xiàn):
簡化后的對象模型
又注意到這里多次以數(shù)組來實(shí)現(xiàn),而編碼過程中必然涉及到數(shù)組的遍歷、查找等操作,JavaScript 1.6 已經(jīng)為我們實(shí)現(xiàn)了這些數(shù)組操作。為了充分利用數(shù)組內(nèi)置的原生方法,又能在較老的瀏覽器中運(yùn)行,我們使用了 Eric 的代碼。這樣,我們可以直接使用諸如 forEach/indexOf 等方法,更關(guān)注組件的功能實(shí)現(xiàn),而且在現(xiàn)代瀏覽器中獲得較好的性能。
~~~~~~~~~~~~~ 八卦分割線 ~~~~~~~~~~~~~
嗯,在嚴(yán)肅地分析了組件設(shè)計之后,就要踏上快樂的編碼實(shí)現(xiàn)之旅了。別急,TaskManager 似乎俗氣了一點(diǎn):不足以表達(dá)具有優(yōu)先級、依賴管理的任務(wù)隊(duì)列,而且用它做命名空間有跟其他代碼沖突的可能性。好吧,這個組件就叫 Smart Queue 吧,響亮而又獨(dú)特.^^
分析設(shè)計好了,名字也有了,欲知具體實(shí)現(xiàn)過程,且聽下回分解。
相關(guān)文章
javascript之textarea打字機(jī)效果提示代碼推薦
非常不錯的提示輸入內(nèi)容,動態(tài)的提示,給人親切感2008-09-09
JS實(shí)現(xiàn)點(diǎn)擊鏈接取消跳轉(zhuǎn)效果的方法
有時候我們僅僅希望將鏈接<a>作為一個按鈕使用,但是在默認(rèn)狀態(tài)下,點(diǎn)擊鏈接會出現(xiàn)跳轉(zhuǎn)效果,下面就通過代碼實(shí)例,介紹一下如何實(shí)現(xiàn)此效果2014-01-01
一個用js實(shí)現(xiàn)過濾重復(fù)字符的函數(shù)
一個用js實(shí)現(xiàn)過濾重復(fù)字符的函數(shù)...2007-08-08
JS實(shí)現(xiàn)倒計時和文字滾動的效果實(shí)例
這篇文章主要介紹了JS實(shí)現(xiàn)倒計時和文字滾動的效果,以實(shí)例的形式分析了倒計時與文字滾動效果的具體實(shí)現(xiàn)方法,并附有js時間變量的說明,非常具有實(shí)用價值,需要的朋友可以參考下2014-10-10
利用Javascript裁剪圖片并存儲的簡單實(shí)現(xiàn)
裁剪圖片對我們來說是再熟悉不過的了,最近工作中就又遇到了這個需求,所以想著干脆整理下來,方法大家和自己在需要的時候參考學(xué)習(xí),所以這篇文章主要介紹了利用Javascript裁剪圖片并存儲的簡單實(shí)現(xiàn),后端PHP處理我用的是THINKPHP框架,需要的朋友可以參考下。2017-03-03
詳解JavaScript Alert函數(shù)執(zhí)行順序問題
本文主要介紹了Javascript的Alert函數(shù)執(zhí)行順序問題,對此感興趣的同學(xué),可以實(shí)驗(yàn)一下,以便解決平時遇到的一些奇怪的問題。2021-05-05

