ko.computed跟踪数组元素的更改

Nat*_*lia 7 knockout.js

有没有办法创建一个ko.computed字段,通知发生在数组元素发生的变化?

我的第一个想法是使用observableArray,但它不起作用,因为

observableArray跟踪数组中的对象,而不是这些对象的状态

不过,我发布这段代码来说明我正在尝试做什么.

HTML:

<div data-bind="foreach:arr">
    <input type="text" value="" data-bind="value: a" />
</div>

<div data-bind="foreach:arr">
    <p>
        Field "a" is changed: <span data-bind="text: aChanged()? 'true': 'false'"></span>
    </p>   
</div>
<p>
    Some "a" field from the array is changed: <span data-bind="text: someAChanged()? 'true': 'false'"></span>
</p>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

function AppViewModel() {
    this.arr = ko.observableArray([new A(), new A()]);
    this.someAChanged = ko.computed(function () {
        var ch = false;
        var arr = this.arr();
        for (var i = 0; i < arr.length; i ++) {
            if (arr[i].aChanged()) {
                ch = true;
                break;
            }
            return ch;
        }
    }, this);    
}

function A() {
    this.a = ko.observable(1);
    this.aChanged = ko.computed(function() { 
        return this.a() != 1;
    }, this);
}

ko.applyBindings(new AppViewModel());
Run Code Online (Sandbox Code Playgroud)

由于我没有权利回答我自己的问题,我在这里发表我的想法.我决定使用"订阅"功能.我的解决方案是添加一个"父"链接到数组的元素.每当可观察字段发生变化时,依赖于其子节点的父字段也会发生变化:

function Child () {
    this._parent = null;
    this.observableField = ko.observable("");
    this.observableField.subscribe(function (newVal) {
         if (newVal... && this._parent) {
             this._parent.anotherObservableField(...);
         }
    });
}
Child.prototype._setParent(parent) {...} 
Run Code Online (Sandbox Code Playgroud)

eri*_*icb 2

您需要确保someAChanged计算结果注册了对数组中每个项目的依赖关系。

像这样的东西应该有效:

function AppViewModel() {
    this.arr = ko.observableArray([new A(), new A()]);
    this.someAChanged = ko.computed(function () {
        var ch = false;
        var changedItem = null;
        var arr = this.arr();

        ko.utils.arrayForEach(this.arr(), function(item){
            var changed = item.changed(); //someAChanged registers a change subscription here

            if(changed && !ch){
                ch = true;
                changedItem = item;
            }
        });

        return changedItem;
    }, this);    
};
Run Code Online (Sandbox Code Playgroud)

本质上,这会为数组中的每个项目注册一个“更改”订阅。您之前的代码在找到的第一个代码处停止,这意味着数组中的其他项目都没有添加“更改”订阅。如果数组中有很多项目,则循环遍历数组中的每个项目并使其成为someAChanged计算的依赖项可能会很昂贵。

上面的代码还将返回第一个更改的项目。我以为这就是你想要的。如果没有,那么重新处理它以返回一组已更改的项目将非常容易。