KnockoutJS 3.X API 第七章 其餘技術(6) 使用「fn」添加自定義函數

有時,您可能會經過向Knockout的核心值類型添加新功能來尋找機會來簡化您的代碼。 您能夠在如下任何類型中定義自定義函數:數組

type-hierarchy

 

由於繼承,若是你附加一個函數到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

如下實例演示如何使用此:繼承

All tasks ( )

Done tasks ( )

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);
相關文章
相關標籤/搜索