有時,您可能會經過向Knockout的核心值類型添加新功能來尋找機會來簡化您的代碼。 您能夠在如下任何類型中定義自定義函數:數組
由於繼承,若是你附加一個函數到ko.subscribable,它將可用於全部其餘的。 若是你附加一個函數到ko.observable,它將被ko.observableArray繼承而不是ko.computed繼承。 app
要附加自定義函數,請將其添加到如下可擴展性點之一: 函數
ko.subscribable.fn
ko.observable.fn
ko.observableArray.fn
ko.computed.fn
而後,您的自定義函數將可用於從該點開始建立的全部類型的值。 this
注意:最好僅將此可擴展點用於真正適用於各類場景的自定義函數。 若是你只打算使用一次,你不須要添加自定義函數到這些命名空間。 spa
這裏有一種方法來定義一個過濾器按屬性函數,將在全部後續建立的ko.observableArray實例上可用:code
ko.observableArray.fn.filterByProperty = function(propName, matchValue) { return ko.pureComputed(function() { var allItems = this(), matchingItems = []; for (var i = 0; i < allItems.length; i++) { var current = allItems[i]; if (ko.unwrap(current[propName]) === matchValue) matchingItems.push(current); } return matchingItems; }, this); }
這返回一個新的計算值,它提供了數組的過濾視圖,同時保持原始數組不變。 由於過濾的數組是一個計算的observable,因此當底層數組發生變化時,它將被從新計算。blog
如下實例演示如何使用此:繼承
UI源碼:get
<h3>All tasks (<span data-bind="text: tasks().length"> </span>)</h3> <ul data-bind="foreach: tasks"> <li> <label> <input type="checkbox" data-bind="checked: done" /> <span data-bind="text: title"> </span> </label> </li> </ul> <h3>Done tasks (<span data-bind="text: doneTasks().length"> </span>)</h3> <ul data-bind="foreach: doneTasks"> <li data-bind="text: title"></li> </ul>
視圖模型源碼:input
function Task(title, done) { this.title = ko.observable(title); this.done = ko.observable(done); } ko.observableArray.fn.filterByProperty = function(propName, matchValue) { return ko.pureComputed(function() { var allItems = this(), matchingItems = []; for (var i = 0; i < allItems.length; i++) { var current = allItems[i]; if (ko.unwrap(current[propName]) === matchValue) matchingItems.push(current); } return matchingItems; }, this); } function AppViewModel() { this.tasks = ko.observableArray([ new Task('Find new desktop background', true), new Task('Put shiny stickers on laptop', false), new Task('Request more reggae music in the office', true) ]); // Here's where we use the custom function this.doneTasks = this.tasks.filterByProperty("done", true); } ko.applyBindings(new AppViewModel());
若是你傾向於過濾可觀察的數組不少,添加一個filterByProperty全局可見的數組可能會使你的代碼更整潔。 可是若是你只須要偶爾過濾,你能夠選擇不附加到ko.observableArray.fn,而只是手工構造doneTasks以下:
this.doneTasks = ko.pureComputed(function() { var all = this.tasks(), done = []; for (var i = 0; i < all.length; i++) if (all[i].done()) done.push(all[i]); return done; }, this);