有时,您可能会通过向Knockout的核心值类型添加新功能来寻找机会来简化您的代码。 您可以在以下任何类型中定义自定义函数:
因为继承,如果你附加一个函数到ko.subscribable,它将可用于所有其他的。 如果你附加一个函数到ko.observable,它将被ko.observableArray继承而不是ko.computed继承。
要附加自定义函数,请将其添加到以下可扩展性点之一:
ko.subscribable.fn
ko.observable.fn
ko.observableArray.fn
ko.computed.fn
然后,您的自定义函数将可用于从该点开始创建的所有类型的值。
注意:最好仅将此可扩展点用于真正适用于各种场景的自定义函数。 如果你只打算使用一次,你不需要添加自定义函数到这些命名空间。
示例:可见数组的过滤视图
这里有一种方法来定义一个过滤器按属性函数,将在所有后续创建的ko.observableArray实例上可用:
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,所以当底层数组发生变化时,它将被重新计算。
以下实例演示如何使用此:
All tasks ( )
Done tasks ( )
UI源码:
<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>
视图模型源码:
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);