如何让ko.computed处理对象内的observable

时间:2014-02-04 13:52:02

标签: knockout.js

我有一个相当简单的视图模型来保存数据数组并获取一个我想用来过滤数据的字符串。

我有一些非常简单的标记来渲染它:

<section class="task-list">
    <ul data-bind="foreach:filteredRecords">
        <li>
            <label>Task name:</label>
            <span data-bind="text:TaskName"></span>              
        </li>
    </ul>
</section>

我已按如下方式设置模型;

var viewModel = {

    searchText : ko.observable(''),
    taskData : ko.observableArray([]),

    searchData : function () {

        // use ko.utils.arrayFilter to limit records by searchText()
        return this.taskData();
    },

    filterRecords: ko.computed(this.searchData, this).extend({ throttle: 500 }),
};

ko.applyBindings(viewModel, $('.task-list')[0]); 

我得到的是

Uncaught Error: Pass a function that returns the value of the ko.computed 

将函数移回ko内部:计算如下:

 filteredRecords: ko.computed(function () {
        return this.taskData();
    },this).extend({ throttle: 500 })

只是告诉我这个错误:

Uncaught TypeError: Object [object global] has no method 'taskData' 

因此尝试定义另一个要使用的属性:

var viewModel = {

    _self : this,

    searchText : ko.observable(''),
    taskData : ko.observableArray([]),

    filteredRecords: ko.computed(function () {
        return this.taskData();
    },this).extend({ throttle: 500 })
};

但现在出现错误

Uncaught ReferenceError: _self is not defined 

最后我尝试这样做:

var viewModel = {

    searchText : ko.observable(''),
    taskData : ko.observableArray([]),

    filteredRecords: ko.computed(function() {
        var me = this;
        return function () {
            return me.taskData();
        }
    },this).extend({ throttle: 500 })
};

现在,这不会抛出任何先前的错误,但也不会在HTML中产生任何结果......

I've set up a Fiddle at

如何正确地将ko.computed应用于对象,以便我可以使用对象中的observable和observableArray?

1 个答案:

答案 0 :(得分:6)

在定义对象文字时,在创建对象文字之前,您无法引用它的任何属性。 this的值不会是您的新对象。

您可以使用类似的构造函数:

var ViewModel = function() {
   this.searchText = ko.observableArray();
   this.taskData = ko.observableArray([]);

   this.filteredRecords = ko.computed(function() {
        //filter logic here, can use `this` and reference searchText/taskData
    },this).extend({ throttle: 500 })
};

然后,创建一个新的实例,如:

ko.applyBindings(new ViewModel(), $('.task-list')[0]); 

否则,您可以在添加计算之前先创建viewModel。然后做:

viewModel.filteredRecords = ko.computed(function() {
  //filter logic here, can use `this` and reference searchText/taskData
}, viewModel);

这个答案也许有帮助:Difference between knockout View Models declared as object literals vs functions