使用嵌套循环更新ViewModel knockout

时间:2015-06-11 19:14:55

标签: javascript jquery knockout.js

这可能不是完成任务的完全理想的优化方式。关于任何更好的方法,我愿意接受建议。到目前为止,负载在性能方面表现良好。

我通过ajax加载我的淘汰应用程序。在绑定调用中,我有一个嵌套循环,其中包含一个根据设置值更新点的函数。

当我尝试添加新项目时,不会抛出任何错误,但UI不会更新,我似乎无法弄清楚原因。

这是我想要做的事情的小提琴。 http://jsfiddle.net/hjchvawr/2/

addCombatant方法确实有效,但无论出于何种原因,表都不会重新绑定。您可以看到VM json中的附加值已输出到控制台。

self.addCombatant = function(combatant){
        ko.utils.arrayForEach(self.divisions(), function(d){
            if(d.name() == combatant.division){
                d.combatants().push({name: combatant.name,
                            ID: combatant.ID,
                            swords:{points: 0, time:'none', kills: 0}
                            });
            }
       console.log(ko.toJSON(self.divisions));
    }
)}.bind(this);

编辑:

我已经应用了下面建议的一些更新,并添加了另一个列表进行排序。它绑定和更新然而,当我添加一个战士时,它只绑定到一个事件并且排序关闭。如果我不能使用sortDivision(战斗员,'剑'),我该如何进行自动分类?在这个小提琴(http://jsfiddle.net/4Lhwerst/2/)中,我希望事件按杀戮排序,然后按时间排序。是否有可能在不创建另一个observeableArray的情况下完成客户端的多级排序?

2 个答案:

答案 0 :(得分:6)

这是你桌子上的foreach绑定。

    <!-- ko foreach: $root.sortDivision(combatants, 'swords') -->

sortDivision已定义:

self.sortDivision = function (div, evt) {
    return div.sortBy(evt, 'time', 'asc').sortBy(evt, 'kills', 'desc');
};

您的sortBy功能会创建一个新的observableArray。这与推送到的observableArray不一样。

ko.observableArray.fn.sortBy = function (evt, fld, direction) {
    var isdesc = direction && direction.toLowerCase() == 'desc';
    return ko.observableArray(this.sort(function (a, b) {
        a = ko.unwrap(evt ? a[evt][fld]() : a[fld]());
        b = ko.unwrap(evt ? b[evt][fld]() : b[fld]());
        return (a == b ? 0 : a < b ? -1 : 1) * (isdesc ? -1 : 1);
    }));
};

您应该将computed s(或pureComputed s)用于重新呈现或重新组合数据的内容。将任何数据项存储在一个位置。

答案 1 :(得分:2)

您正在推进潜在的战斗人员阵列,从而绕过变更跟踪。完成后删除括号(d.combatants.push)或调用valueHasMutated。

您需要:

    if(d.name() == combatant.division){
        d.combatants.push({name: combatant.name,
                    ID: combatant.ID,
                    swords:{points: 0, time:'none', kills: 0}
                    });
    }

或者:

    if(d.name() == combatant.division){
        d.combatants().push({name: combatant.name,
                    ID: combatant.ID,
                    swords:{points: 0, time:'none', kills: 0}
                    });
        d.combatants.valueHasMutated();
    }