先前範例中出現的ko.computed()多用於對其他屬性值進行組合或運算,屬唯讀性質。但ko.computed()也支援寫入功能,可將寫入的新值經處理運算後用於更新相關屬性。

針對可寫入式ko.computed,宣告時將不再只傳入單一function,需分別宣告讀、寫對應的函數:

self.boo = ko.computed({
    read: function() { ...傳回運算結果... },
    write: function(value) { …取得新值,更新相關屬性... }
});

除read, write外,還有一些額外參數:

  • owner:
    用以指定read/write函數執行時"this"所指的對象,若ViewModel有依循另行宣告self變數的慣例(請參考範例1的補充說明),則在read/write可使用self代表ViewModel,便可忽略本參數。
  • deferEvaluation:
    設為true時,computed會在被讀取時才運算,在某些情境下可減少非必要的CPU資源消耗。(預設行為是參考到的屬性一有變化就重算)
  • disposeWhen:
    可指定一傳回true或false的函數,每次重算結果時會檢查此函數,當傳回結果為true,則抛棄這個computed(實際意義是取消對所依賴屬性的訂閱行為,之後該屬性變動也不再重算,避免無謂的運算消耗)
  • disposeWhenNodeIsRemove:
    可指向特定的DOM元素,一且被從DOM移除,就抛棄該computed。(在if/with等範本情境中,可在繫結對象消失後馬上停用不必要的重算行為)

以下是一個簡單可寫式computed範例,分別可輸入經度(latitude)及緯度,另外使用computed將經緯度加上逗號組合成location屬性顯示於TextBox(即下圖的Location欄位),若修改Location欄位字串內容,也會反饋更新經度或緯度數字: 線上展示

完整程式碼如下:

<!DOCTYPE html>
 
<html>
<head>
    <title>Lab 16 - 可寫式ko.computed()</title>
    <script src="../Scripts/jquery-1.7.2.js"></script>
    <script src="../Scripts/knockout-2.1.0.debug.js"></script>
    <script>
        function MyViewModel() {
            var self = this;
            self.latitude = ko.observable(23.5);
            self.longitude = ko.observable(121.5);
            self.location = ko.computed({
                //讀取時傳回經緯度合併
                read: function () {
                    return self.latitude() + "," + self.longitude();
                },
                //寫入時拆解成兩欄,檢核未過時不處理
                write: function (value) {
                    var p = value.split(',');
                    if (p.length == 2 && !isNaN(p[0]) && !isNaN(p[1])) {
                        //檢核成功, 分別設定緯度、經度
                        self.latitude(p[0]);
                        self.longitude(p[1]);
                    }
                }
            });
        }
 
        $(function () {
            ko.applyBindings(new MyViewModel());
        });
    </script>
</head>
<body>
    <dl>
        <dt>Latitude</dt>
        <dd><input data-bind="value: latitude" /></dd>
        <dt>longitude</dt>
        <dd><input data-bind="value: longitude" /></dd>
        <dt>Location</dt>
        <dd><input data-bind="value: location" /></dd>
    </dl>
    <input type="button" value="Do Nothing"/>
</body>
</html>

[KO系列]

http://www.darkthread.net/kolab/labs/default.aspx?m=post

Comments

Be the first to post a comment

Post a comment