分離的 DOM

2014 年 1 月 16 日

單頁式網頁應用程式經常變成 jQuery 大雜燴,其中應用程式邏輯、DOM 處理和伺服器存取全部混在一起。這種混雜的考量讓此類應用程式比它們應有的更難以理解和測試。分離的 DOM 是一種模組化策略,可將 DOM 的所有處理分隔到專用的 JavaScript 物件中。

舉例來說,考慮我最近開發的 過濾目錄頁面,用來討論我最喜歡的歐式遊戲。此頁面的關鍵行為是您可以在左側的過濾面板上按一下,以過濾在項目清單面板中顯示哪些遊戲。這一切都是透過 JavaScript 執行的。我為過濾面板和項目清單建立了 JavaScript 類別,每個類別都封裝了該頁面部分的 DOM 存取。決定要顯示哪些遊戲的邏輯保存在控制器類別中,該類別使用獨立於 DOM 的介面與 DOM 處理類別對話。控制器類別不會使用任何 jQuery。

在初始化期間,控制器會將其更新函式傳遞給 Filter DOM,以便在過濾器中的方塊變更狀態時呼叫,Filter DOM 會將此函式設定為核取方塊的按一下事件。因此,當過濾器顯示中的任何項目變更時,控制器中的此更新函式會要求 Filter DOM 類別提供其主動過濾器 ➊。Filter DOM 類別會使用 jQuery 尋找適當的 HTML 元素來回應此呼叫 ➋,篩選出已勾選的方塊,並以一個簡單的資料結構回應控制器,指出每個群組中哪些方塊已勾選 ➌。

控制器會使用此過濾器狀態資訊來決定現在應該哪些遊戲可見,將它們分成左右兩欄,並呼叫 Entry List DOM,提供清單中應顯示哪些元素 ID 的詳細資料 ➍。Entry List DOM 會使用 jQuery 將 HTML 項目洗牌到正確的 div 中,以完成工作 ➎。

這樣做的主要好處是,讓每個類別專注於單一任務,進而更容易推論。當我處理 Filter DOM 類別時,我會專注於如何對 HTML 元素執行 DOM 操作。當我處理控制器時,我可以忽略 HTML 結構、css 類別名稱等詳細資料。

在更抽象的模式術語中,這些 DOM 物件充當 閘道,也就是兩個 界限脈絡(應用程式和 HTML DOM)之間的通道。與任何閘道一樣,DOM 物件有一個介面,會說其客戶端(應用程式)的詞彙,並有一個實作,會將此翻譯成彼岸的蠻荒之地(HTML DOM)。[1]

良好的模組化設計往往與可測試性相關。每個類別都可以在相對孤立的環境中進行測試。區隔 DOM 的一個特定優點是,我可以測試控制器,而不用瀏覽器或 PhantomJS 等模擬瀏覽器。由於不需要 DOM 來測試控制器,因此可以在節點中測試它,並僅提供一些簡單的測試替身給 DOM 閘道。這使得修改控制器更快速、更容易。透過盡可能將邏輯從 DOM 閘道中移出,我可以增加在不訴諸 PhantomJS 等工具的情況下可以執行的測試數量(謙卑物件 模式的應用)。

延伸閱讀

Pete Hodgson 是本文構想的寶貴來源。巧合的是,他自己的關於使用區隔 DOM 的文章 在同一天發表。它有更多詳細資訊和一個簡短範例。

致謝

Pete Hodgson 給了我一些有用的構想,用於改善本文。

註解

1: 你可以對伺服器存取使用類似的區隔 - 這是 閘道 的經典應用。