第192期 / October 5, 2013

分享到臉書!分享到維特!分享到噗浪!分享到Google+!分享到微博!轉寄友人友善列印

淺談 Knockoutjs

作者/許文瀚

[發表日期:2013/10/4]

簡介

互動式的網頁,對於服務端回應使用者端之速度而言從以前至現在已增快許多,藉由framework的結構精進了網頁的反應速度及順暢度。再者,資料存取與傳輸方式都能減輕服務端的CPU時間。並將JavaScript framework複雜的組織慢慢趨於簡單且模組化。將網頁元件與程式邏輯分別處理也變得更容易維護。而在眾多的前端語言中,Knockout屬於JavaScript framework MVC的一種前端語言。它能透過分層的Model-View-ViewModel(MVVM)設計模式來開發網站,對於網頁處理新增、查詢、修改、刪除Create-Read-Update-Delete(CRUD)資料的應用是可被納入考慮的開發框架。

何謂MVVM

MVVM的架構圖由三個區域所組成,分別為View、ViewModel、Model。View負責使用者控制項的部分,ViewModel視為View的抽象層,實現View與Model之間資料傳遞,Model為被操作的資料對象。

圖一對一些可編輯的html控制項(Textbox、CheckBox)或點選按鈕(Button),會使資料在View與ViewModel的Data產生連動效應。使用者變更UI控制項內容,在ViewModel相對應的資料自動被更新;當ViewModel內容更動,也能被反映在View的資料上。此種雙向資料連動的概念類似雙向綁定(Two-Way Binding),以往作法是某個控制項發生改變,通知被觸發的事件並更新資料內容,過程過於繁雜。


《圖一》MVVM架構圖


而MVVM結構實現讓開發者專注於處理資料邏輯,Knockout透過MVVM設計模式負責View與ViewModel的關聯性,其主要特色有以下幾種:
1.宣告綁定:透過DOM元素的屬性植入資料綁定(Data Binding)。
2.相依追蹤:資料模型(Model)變更,View中對應UI控制項內容同步改變。
3.高彈性的樣板(template):可任意嵌入複雜動態的UI樣式。
根據以上特點,藉由基本範例程式瞭解資料綁定及相依追蹤如何運作。

介紹範例程式之前,實作Knockout可由以下兩種方式達成。一種採用圖二官方網站的框架,分成View(html)與ViewModel(JavaScript)及輸出結果(Output),直接填入對應的程式區塊,立即得到結果。


《圖二》Knockout官網的程式框架


另一種方式則使用Microsoft Visual Studio 2012的NuGet下載程式庫,搜尋knockout執行安裝即可立即使用。便於完整的開發框架,範例程式會以Asp .net MVC4網站結合knockout為主。


《圖三》使用NuGet套件搜尋knockout函式庫


範例一以人的資訊(姓名、住址、Email)結合html控制項(input、span)呈現UI控制變更時的同步效果。首先如圖(4)紅框部分在View頁面下的html中,之間加上knockout的函式庫,必要時也可加入jQuery函式庫。


《圖四》在head間加入knockout和jQuery函式庫


完成後,圖五在間開始設計View的UI控制項,加入三個input及三個span控制項,根據View控制項植入宣告資料綁定(data-bind)屬性,不僅綁定html中的元素value與text,亦能連結至ViewModel定義的屬性。

以圖六所示,ko.applyBindings()函式將View中的控制項元素綁定至PersonViewModel。綁定的資料屬性名稱如:Name、Address、Email必須與UI控制項一致,透過Knockout的可觀察(observable)函式,能隨時追蹤屬性的變化。因此給予PersonViewModel屬性初始值,View中控制項的內容也能隨之改變如圖七所示。當使用者輸入姓名input控制項(紅框)完畢後點選tab鍵,span元素內容(藍框)會立即改變如圖八。


《圖五》在body間加入UI控制項



《圖六》View控制項經由applyBindings函式綁定至PersonViewModel,PersonViewModel裡的資料屬性(Name, Address, Email)必須與View(UI)控制項的名稱一致



《圖七》View控制項內容為PersonViewModel預設的初始值



《圖八》使用者在input控制項輸入姓名(紅框部分),span區域(藍框部分)自動更新


範例二為人員的基本資料透過樣式(template)的方式建構出多個重複的使用者介面。如圖九所示,在View中
區塊裡綁定template,定義出使用者介面的區塊name: peopleInfo以及使用foreach擷取多筆人員基本資料內容。圖十為peopleInfo的人員區塊UI,包含name、phone、address、email,此區域能利用foreach得到多組人員資訊,共同使用自訂好的同一個template,生成多個重複的使用者介面。


《圖九》綁定template透過foreach複製多個重複使用者介面



《圖十》自定義的使用者介面(peopleInfo),此區域程式碼能被重複利用


圖十一定義一個ViewModel為InfoModel,給予多筆人員基本資料,藉由applyBindings函式綁定View之控制項與ViewModel的資料屬性。每加入一組人員資訊必須呼叫Info函式。完成後,第一筆人員資料會置於people變數中,同時InfoModel因為observableArray函式,people資料異動時亦能立即被偵測如圖十二。依此類推,people變數透過圖九的foreach取得三筆人員資料,依據使用者設計單一界面,將三筆人員資料套用template後呈現的結果如圖十三。


《圖十一》在InfoModel給予多筆人員資料並綁定View中控制項的資料屬性



《圖十二》InfoModel利用observableArray函式聆聽people的資料內容,Info函式定義人員資料內容



《圖十三》使用template方式,多個不同資料內容可以共享同一個使用者設計介面


範例三為利用唯讀控制項相依追蹤至input控制項。以圖十四而言在View中宣告兩個控制項分別是txtWord1與txtWord2,以及相依追蹤的唯獨控制項firstWord與secondWord和一個span控制項用來顯示相依追蹤是否成功。

並藉由圖十五applyBindings函式將View連結至MyViewModel,分別對txtWord1、txtWord2、firstWord與secondWord進行聆聽,當資料發生改變時,同步更新控制項內容。為了追蹤兩個input控制項,使用Computed函式可以重新定義控制項的綁定,如圖十六當txtWord1控制項內容為close,在txtWord2上輸入任何內容,secondWord(綠框區域)對txtWord2的相依追蹤失效,observable函式不會被觸發,在(藍框區域)將顯示追蹤失敗。


《圖十四》兩個input控制項txtWord1、txtWord2,及追蹤input控制項firstWord與secondWord



《圖十五》透過applyBindings從View中建立連結至MyViewModel,txtWord1、txtWord2、firstWord和secondWord控制項,自訂條件限制影響Observable是否觸發,並藉由Computed函式,重新建立綁定關係



《圖十六》尚未輸入close單字,相依追蹤能成功;反之,追蹤將失敗


根據以上三點特性的介紹,從範例可以了解knockout專注於數據的綁定,並套用template的使用方式看出它巧妙的地方。不過缺乏了routing功能,無法直接使用網頁展示,但能結合第三方函式庫(Sammyjs)提供route層並藉由Ajax加載數據實現。

Knockout.js 與 Angular.js 比較

Anugular是MVC的一種框架,同樣擁有雙向綁定(Declarative bindings)、相依追蹤與樣板的功能以及能與jquery做結合。不同的是,多了end to end testing(測試)、route與依賴注入(injection)功能。

在圖十七顯示了Knockout的函式subscriber 與Angular的函式watch,兩者皆為監聽控制項的變化,研究人員的文獻中使用更新一百個控制項的方法,測試此兩種框架在Chrome能處理operator數目,分別執行十次與一百次迴圈,可以發現Knockout每秒可執行的運算數都比Angular還來得多。


《圖十七》使用Chrome平台測試Knockout的函式subscriber和Angular的函式watch比較每秒所能執行的運算數


而目前Web應用開發傾向於前端架構的方向發展,由於JavaScript是個活用的語言,當解決一種問題時,不同背景的開發人員透過不同設計理念來完成JavaScript框架,進而衍生多種單頁應用設計模式的問題。以下介紹何謂單頁應用設計:例如Backbone.js、Angular.js及本文介紹Knockout.js等。這些框架對使用者體驗擁有的流暢度、使用者介面的反應速度,以及服務請求較少都是單頁應用設計的優點。若需要完成互動複雜的大型 Web應用,也需要一個量身訂做的前端架構來支援。

如何選擇合適的JavaScript框架來開發,需從很多角度進行探討:

1.端看此框架採取甚麼樣子的設計模式:是MVC(Angular.js)、MVP(Backbone.js)還是MVVM(Knockout.js)?

2.View的處理,對於JavaScript現有的DOM添加行為(Angular.js、Knockout.js),或是基於模板渲染成DOM(Backbone.js)?

根據這些問題,因開發人員本身的喜好與習慣不相同,藉由目前這些有支援JavaScript框架社群獲取一些想法作為未來開的依據。這些JavaScript框架要學習與比較,能透過TodoMVC網站包含了各種流行的框架實現Todo的功能達到相同的效果,有助於我們能理解這些框架語法與結構不同。

那當接到一個專案時,我們該如何選擇、該考慮些甚麼變得十分重要。相關研究文獻指出五點需要考慮的地方:

1.專案規模大小:大規模的專案開發須重視框架:成熟度。確保專案的品質:可測試性與可維護性;反之,小規模的專案開發需有良好的靈活性、能有較高的兼容性。

2.開發團隊的現有資源:是否已經對某些框架及工具有一定的實戰經驗?是否在後端技術有一定偏好?團隊中若選用不熟悉的框架,消耗學習的人力成本及衡量選用的框架帶來的利益是否能達到平衡。

3.開發出的產品對用戶體驗的需求:產品本身適合傳統的Web應用還是單頁應用更適合?產品若對使用者介面組件需求龐大時,是否需要著重每一個細節?

4.全面的文檔:任何框架應有一系列的文檔幫助開發人員能迅速的了解框架的API有哪些。

5.框架擅長的功能:開發人員必須了解各個前端技術官方網站所提供框架的功能列表,確保你真得研究過以便未來能很快的延用這些框架。
因此對於選擇框架時,必須對團體中每個人各個負責項目進行定位,整合出一套具體技術的需求文件,根據需求文件尋找出團隊中最合適的前端技術語言(Knockout.js、Angular.js、Backbone.js等)與工具。

參考文獻

1.http://knockoutjs.com/
2.http://angularjs.org/
3.http://todomvc.com/
4.http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
5.http://msdn.microsoft.com/zh-tw/library/windows/apps/jj160324.aspx
6.http://en.wikipedia.org/wiki/JavaScript