计算值的数组语义

时间:2012-04-22 20:58:04

标签: knockout.js

我有一个代理集合的ko.computed()函数:

function ListView(query) {
    var self = this;

    this.query = query;
    this.items = ko.observableArray([]);
    ko.computed( function() {
        self.items( self.query() == null ? [] : self.query().postings() );
    }

    // more code
}

不幸的是,这导致self.items()变量随着postss()数组中每个对象的每次更改而改变。我宁愿做的是有一个计算值项直接代表查询的帖子。但如果我这样做:

 self.items = ko.computed(function() { return self.query().postings(); });

就Knockout而言,该值变为标量,而不是数组。重要的原因是,由于列表中的某些项目会更改状态,因此我想更新显示的那些部分,而不是重新渲染整个列表。这不仅仅是性能优化(虽然有数百个项目的性能也是一个问题),但我也在尝试记录当前正在显示哪些项目以跟踪用户可能看到的内容。

我认为逻辑上,我希望有这样的东西:

  self.items = self.query().postings;

但如果查询发生更改,则会中断,因为(我认为)依赖项存在于其他对象上。

是否有一种干净的方法来构建依赖机制并仍然保留集合语义?

已编辑:2012年5月13日

我尝试实现@MichaelBest建议的扩展方法,但是产生了以下错误:

Uncaught TypeError: Object function dependentObservable() {
        if (arguments.length > 0) {
            set.apply(dependentObservable, arguments);
        } else {
            return get();
        }
    } has no method 'valueWillMutate'
ko.utils.arrayForEach.ko.observableArray.fn.(anonymous function)    knockout-2.1.0.debug.js:1087
SubviewModel.self.refresh.self.doSort    SummaryViewModel.js:73
ko.ignoreDependencies    knockout-deferred-updates.js:172
subFnObj.(anonymous function).newCallback    knockout-deferred-updates.js:188
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:870
ko.utils.arrayForEach    knockout-2.1.0.debug.js:85
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:866
evaluateImmediate    knockout-deferred-updates.js:300
evaluatePossiblyAsync    knockout-deferred-updates.js:246
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:870
ko.utils.arrayForEach    knockout-2.1.0.debug.js:85
ko.subscribable.fn.notifySubscribers    knockout-2.1.0.debug.js:866
ko.observable.observable.valueHasMutated    knockout-2.1.0.debug.js:946
observable    knockout-2.1.0.debug.js:934
updateViewModel    knockout.mapping-latest.debug.js:514
changes    knockout.mapping-latest.debug.js:389
visitPropertiesOrArrayEntries    knockout.mapping-latest.debug.js:569
updateViewModel    knockout.mapping-latest.debug.js:374
ko.mapping.fromJS    knockout.mapping-latest.debug.js:91
Topic.load    querium.js:1212
...

2 个答案:

答案 0 :(得分:3)

您可以创建一个返回数组的计算observable,其行为类似于observableArray

self.items = ko.computed({
    read: function() { return self.query().postings(); }
    write: function(value) { self.query().postings(value); }
});
ko.utils.extend(self.items, ko.observableArray.fn);

现在,您可以使用observableArrayitems的所有功能。

修改:此方法仅在您向对象添加valueWillMutatevalueHasMutated函数时才有效:

self.items.valueWillMutate = function () { self.query().postings.valueWillMutate(); }
self.items.valueHasMutated = function () { self.query().postings.valueHasMutated(); }

这只有在你使用Knockout的 debug 版本时才有效,因为在 minified 版本中,函数名称将被压缩。

答案 1 :(得分:0)

您可以让computed返回一个observable:

self.items = ko.computed(function() { return self.query().postings; });

然后您可以像这样使用代理observableArray

self.items().push(...);

要访问基础数组,您必须打开两个observable:

var postingsArray = self.items()();