knockout.js是一套令人驚豔的JavaScript MVVM程式庫,透過MVVM的運作原理,開發程式時只需專注於定義ViewModel邏輯,不需耗費心力處理TextBox、Select的onchange、onclick等互動細節,就能實現UI元素與資料天人合一的境界。身為網頁開發老鳥,雖早已具備徒手打造類似互動網頁的能力,但在領略過knockout.js的簡潔精巧、強韌不易出錯,相見恨晚的心情油然而生... 如此神兵利器,不多善用實在可惜,這一系列的KO範例也是我的學習筆記,將逐一探討knockout.js在常見網頁情境上的應用。

knockout.js介紹文已示範過最簡單的應用,為<input>與<span>加上data-bind宣告,透過ko.applyBindings()繫結到定義好的ViewModel上,當input改變輸入內容,會立即反應在span。然而,有些場合資料需經加工才能使用,例如: 指定日期格式,將數字加總... 等等,此時ko.computed()便派上用場。

使用ko.computed()時,最簡單的做法是直接傳入function,在其中引用其他的ViewModel屬性處理運算後傳回結果;因knockout具備強大的相依關係追蹤能力,能記下你引用了哪些屬性,一旦被引用的屬性來源改變,便會呼叫ko.computed()計算新值。在範例1中,我們在MyViewModel定義了firstName及lastName兩個屬性,宣告成ko.observable(),knockout便能察覺其變更時機以觸發相關動作。而fullName是一個計算型屬性 -- ko.computed(),在函數中以firstName()及lastName()取得當下的內容組合成單一字串輸出。由於firstName/lastName是ko.observable(),如要取用其值要把它當成函數呼叫,例如: firstName()即會傳回"Jeffrey";要設定新值時,也要視為函數操作,寫成fistName("New Value")。

另外補充,在宣告ViewModel時,建議依循範例中的寫法,將ViewModel宣告成一個function,內部用var self = this;方式以self變數取代this指向ViewModel自己。因在ko.computed函數或一些事件函數中this可能指向其他個體,一律改以self代表ViewModel個體,可避免無謂混淆,這也是KO文件中建議的做法(參考說明文件A popular convention tht simplifies things一節),之後所有範例都將依循此一慣例。

範例程式碼如下,其中宣告了firstName及lastName兩個ko.observable()屬性,fullName則為ko.computed()將firstName與lastName組成一個字串後輸出。而firstName/lastName繫結至<input>,fullName則繫結至<span>。試著修改firstName及lastName的內容,可觀察到一旦firstName或lastName內容有所改變(預設為onchange事件觸發),fullName就會立即重新運算,並即時反應在span上,相較以前要自己在兩個<input>上攔截onchange事件處理,著實乾淨俐落許多(有自己土法鍊鋼玩過,感觸特別深),然而這只是開端,後面還會陸續看到knockout.js更多讓人嘆為觀止的精彩表演,敬請拭目以待~

<!DOCTYPE html>
 
<html>
<head>
    <title>Lab 1 - 計算型屬性</title>
    <script src="../Scripts/jquery-1.7.2.js"></script>
    <script src="../Scripts/knockout-2.1.0.js"></script>
    <script>
        //將ViewModel宣告成function,方便擴充額外功能
        function MyViewModel() 
        {
            //由於this在不同範圍代表意義有別,
            //習慣上會用self代表ViewModel本體,不易混淆
            var self = this;
            self.firstName = ko.observable("Jeffrey");
            self.lastName = ko.observable("Lee");
            //使用ko.computed宣告函數,透過運算產生屬性值
            self.fullName = ko.computed(function () {
                //透過ko.observable宣告的屬性,
                //要用propName()方式取得最新結果
                return self.firstName() + " "
                           + self.lastName();
            })
        }
        $(function () {
            //使用new MyViewModel()產生一個ViewModel個體
            ko.applyBindings(new MyViewModel());
        });
    </script>
</head>
<body>
<input type="text" data-bind="value: firstName" />
<input type="text" data-bind="value: lastName" />
<br />
<span data-bind="text: fullName"></span>
</body>
</html>

本範例另有線上展示,歡迎試用~~

[KO系列]
http://www.darkthread.net/kolab/labs/default.aspx?m=post

Comments

Be the first to post a comment

Post a comment