在Knockout預設機制中,能感應ViewModel屬性的改變,自動更新UI元素或是依據依賴關係重算ko.computed()函數,除此之外,我們還能"訂閱"屬性改變事件,以便在屬性值被修改時執行特定邏輯。

第一種做法是利用ko.observable()的.subscribe()訂閱,例如:

viewModel.someProp.subscribe(function(newValue) { 
    //在本例中, someProp是一個ko.observable() 
    //此段程式會在sombProp被賦與新值時被觸發,並可由newValue取得新值 
});

第二種方法則是先為ko.observable擴充自訂方法,之後再透過.extend()呼叫該方法執行訂閱動作,當有多個屬性都要執行相似訂閱行為時,此種寫法較有效率:

ko.extenders.addLog = function(target, custOptions) { 
    //target為ko.observable,亦即訂閱對象 
    target.subscribe(function(newValue) { … }); 
    //將target傳回,以便串接其他方法 
    return target; 
} 
//呼叫擴充方法,自訂參數custOptions用不到,傳入null; 
viewModel.somePorp.extend({ addLog: null  });

在以下範例中,ViewModel有name及score兩個屬性,程式分別示範直接訂閱及透過擴充方法,在屬性變化時跳出alert訊息。線上展示

完整程式碼如下:

<!DOCTYPE html>
 
<html>
<head>
    <title>Lab 15 - 訂閱屬性變更事件</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.name = ko.observable("Jeffrey");
            self.score = ko.observable(32767);
        }
 
        var viewModel = new MyViewModel();
 
        //** 方法1 **
        //直接訂閱,在屬性變化時執行指定邏輯
        viewModel.name.subscribe(function (newValue) {
            alert("Name = " + newValue);
        });
 
        //** 方法2 **
        //透過extenders為observable加上擴充功能
        //在ko.extenders上宣告新方法alertChange,
        //第一個參數為observable本身
        //第二個參數為呼叫時傳入自行定義的額外物件,本例中為標題文字
        ko.extenders.alertChange = function (target, header) {
            target.subscribe(function (newValue) {
                alert(header + " -> " + newValue);
            });
            //傳回observable本身, 以支援串接寫法
            return target;
        }
 
        //透過observable().extend()可呼叫先前定義的擴充功能
        viewModel.score.extend({ alertChange: "[Score]" });
 
        $(function () {
            ko.applyBindings(viewModel);
        });
    </script>
</head>
<body>
    <dl>
        <dt>Name</dt>
        <dd><input data-bind="value: name" /></dd>
        <dt>Score</dt>
        <dd><input data-bind="value: score" /></dd>
    </dl>
</body>
</html>

[KO系列]

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

Comments

Be the first to post a comment

Post a comment