KnockoutJS 3.X API 第七章 其他技术(6) 使用“fn”添加自定义函数

有时,您可能会通过向Knockout的核心值类型添加新功能来寻找机会来简化您的代码。 您可以在以下任何类型中定义自定义函数:

type-hierarchy

 

因为继承,如果你附加一个函数到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);
posted @ 2016-10-19 11:13  SmallProgram  阅读(1040)  评论(0编辑  收藏  举报