如果說jQuery是林志玲,那麼knockout.js可比陳妍希,同樣讓人一見傾心!! 這就是我初見knockout.js的感想。
knockout.js是一套JavaScript UI程式庫,主要用來在網頁實現MVVM設計模式。MVVM已在微軟WPF/Silverlight/WP7中廣泛應用(延伸閱讀: InfoQ的簡要介紹、微軟的MVVM導論、天空的垃圾場則有幾篇WPF MVVM入門範例),用白話來說:
在MVVM裡,UI操作涉及的資料被包成ViewModel類別,接著在UI輸入/顯示元素分別標註其對應到ViewModel某個屬性值。當程式碼改變ViewModel屬性值,其對應的輸入/顯示欄位元素便會自動更新;而在UI欄位填入不同內容,ViewModel的資料屬性也會立刻被修改為新值。
這種雙向繫結(Two-Way Binding)的概念,若使用傳統做法得在ViewModel的屬性修改事件寫程式將新值反應到某個顯示/輸入元素上,還得攔截輸入元素的onChange事件,用程式將最新輸入結果反應到ViewMode屬性上,瑣碎的實做細節蠻多的。而不管是Silverlight/WPF或JavaScript,MVVM程式庫的目標即在節省前述自行開發的工夫,只需在顯示/輸入元素上註明其對應的ViewModel屬性,之後全部交給程式庫自動處理,讓程式開發者能優雅地實現MVVM。
如今,MVVM概念也被搬到網頁開發上,未來大家在ASP.NET MVC的展示中應就會常看到它。在JavaScript領域,過去也有些MVVM程式庫被提出來,例如: 微軟主導的jQuery Data Link Plugin(不過,它跟jQuery Template Plugin一樣,已停止發展,未來會由jsView及jsRender接替,但預估要到2012年中才會進入Beta階段),但顯然都比不上knockout.js所受到的關注與歡迎。
knockout.js的主要特色為:
- 宣告式語法: 透過DOM元素Attribute宣告完成資料繫結(Data Binding),簡潔方便
- 自動UI更新: 只要Model資料改變,UI立即反映
- 相依性追蹤: 源頭資料變動時,可自動追溯所有關連的資料一起改變
- 支援範本(Template): 開放自訂Template決定Model資料輸出結果,可滿足各式客製需求
- 免費、Open Source
- 純JavaScript - 可跟jQuery或其他JavaScript Framework併用無虞
- 輕薄短小,Minified版本只有40KB,HTTP壓縮後只有14KB
- 跨瀏覽器! 支援IE6+, FF2, Chrome, Opera, Safari(含行動裝置版本)
要開始體驗knockout.js,建議可由官方網站上超神奇的Web互動教學入門:
教學網站如上所示,網站左上區塊為操作說明,右上為HTML標籤區,右下方為程式碼區,左下區塊則可立即測試結果。按照操作說明,一個步驟一個步驟在HTML區及程式碼區輸入適當的標籤及程式碼,就能立即體驗knockout.js的魔力。另外,官方網站也有極其詳盡的Knockout API說明,則是深入了解knockout.js的有效途徑。
要在ASP.NET專案中體驗knockout.js,最簡單的方法是透過NuGet下載程式庫:
接著寫幾行程式,就能體驗MVVM的威力,如以下的範例:
<!DOCTYPE html>
<html>
<head>
<title>knockout.js First Lab</title>
<script src="../Scripts/knockout-2.1.0.debug.js"></script>
</head>
<body>
<input type="text" id="txtValue" data-bind="value: myValue" />
<span id="spnValue" data-bind="text: myValue"></span>
<script type="text/javascript">
var myViewModel =
{
myValue: ko.observable("Darkthread")
}
ko.applyBindings(myViewModel);
</script>
</body>
</html>
在以上網頁,我宣告了一個<input>一個<span>,並定義了只有一個myValue屬性的超簡單ViewModel: myViewModel物件。透過data-bind="value: myValue"將myValue屬性綁到<input>的value值,透過data-bind="text: myValue"將屬性反映到<span>中,而myValue需透過ko.observable()宣告,knockout.js才能偵測到屬性值的變化,以便連動所有相關的UI元素。最後,要呼叫ko.applyBindings()將myViewModel繫結到網頁元素上,由於本例未引用jQuery,無$.ready()可用,所以把<script>放在網頁的最後端以確保ko.applyBindings()在網頁元素都載入後才執行。
網頁運行後,<input>與<span>一開始會顯示Darkthread,試著改變<input>的值,可發現<span>會馬上反應修改後的結果。很酷吧!!
我對ASP.NET MVC 4提到的SPA(Single Page Application)很有興趣,而knockout.js是其中重要的一環,將陸續分享一些學習心得。
PS: SPA最簡單的比喻就是像GMail那種在同一個網頁中做完全部操作,不觸發任何PostBack的設計哲學。之前我在jQuery教學中也做過粗淺示範,但當時是純手工打造,未來在ASP.NET MVC架構下實現,已有許多現成配套,相關的3rd Party程式庫也更成熟,將會省力很多。