knockout.js - 计算值的数组语义

标签 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()变量随着对 posts() 数组中每个对象的每次更改而更改。我宁愿做的是让一个计算值项目直接代表查询的帖子。但如果我这样做:
 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
...

最佳答案

您可以创建一个计算出的 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);

现在您可以使用 observableArray 的所有功能。已与 items .

编辑:此方法仅在您还添加 valueWillMutate 时才有效和 valueHasMutated对象的函数:
self.items.valueWillMutate = function () { self.query().postings.valueWillMutate(); }
self.items.valueHasMutated = function () { self.query().postings.valueHasMutated(); }

而且这也只有在您使用 Knockout 的调试版本时才有效,因为在缩小版本中,函数名称将被压缩。

关于knockout.js - 计算值的数组语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10272058/

相关文章:

javascript - 如何正确显示我的 Knockout 应用程序的模板元素?

javascript - Knockout JS 模板 HTML 无法正确呈现

javascript - 如何将元素传递给 JavaScript 函数并访问第一个子元素

jquery-ui - jQuery UI Sortable 的 knockout 自定义绑定(bind) - 奇怪的行为

javascript - 如何使用同位素为 Knockout observableArray 中的项目布置 HTML 元素?

javascript - 使用具有可观察属性的自定义对象进行 knockout 绑定(bind)选择

javascript - Knockback.js 主干集合仅将第一个元素添加到 UI

knockout.js - 如何使用 ko.mapping 只观察一个键

javascript - knockout.js 从另一个 View 模型初始化 View 模型

javascript - 仅当从列表中选择一个特定选项时才显示相关内容