具有排序和Foreach数据绑定的Knockout Observable Array

时间:2014-01-21 20:08:54

标签: arrays sorting knockout.js foreach computed-observable

我有一个对象数组,这些对象被连接到一个可拆卸的可观察数组中。我需要对这些数组应用排序,然后遇到一些有点令人困惑的行为。

我的第一次尝试涉及在foreach数据绑定中应用排序 http://jsfiddle.net/wnfXV/

<ul data-bind="foreach: people.sort(function(l,r) { return l.name == r.name ? 0 : (l.name < r.name ? -1 : 1)})">

这会执行正确的排序,但我无法动态添加/删除数组中的元素并进行DOM更新。

如果我添加一组括号来访问底层JavaScript数组,一切正常。

<ul data-bind="foreach: people().sort(function(l,r) { return l.name == r.name ? 0 : (l.name < r.name ? -1 : 1)})">

基于我发现的一些SO答案,我最终为排序的数组创建了一个计算的observable。 http://jsfiddle.net/wnfXV/2/

self.sortedPeople = ko.computed(function() {
    return self.people().sort(function(l,r) {
        return l.name == r.name ? 0 : (l.name < r.name ? -1 : 1);
    });
});

这也有效。而且我甚至不需要数据绑定到计算的observable,因为它立即执行。我可以适当地推送和删除数组项和DOM更新。

但是,如果我将代码更改为:

self.sortedPeople = ko.computed(function() {
    return self.people.sort(function(l,r) {
        return l.name == r.name ? 0 : (l.name < r.name ? -1 : 1);
    });
});

现在,我可以将项目推送到数组并更新DOM,但数据未被排序。

我认为这些差异与淘汰依赖关系跟踪有关,以及在可观察数组上运行与其下的本机JavaScript数组之间的区别,但我很难概念化行为发生变化的原因。我能够让它发挥作用,但我也很好奇什么是最佳实践。

感谢您的帮助。 :)

2 个答案:

答案 0 :(得分:2)

KO实际上不推荐在视图中使用排序的问题,因为 使用这种方法 observableArray.sort不会在数组上建立依赖,因此绑定不会更新。

因此,如果你想让它工作,可以使用

items.slice(0).sort()

更详细的了解一下 https://github.com/knockout/knockout/issues/1380

小提琴:http://jsfiddle.net/mbest/6dmAn/

答案 1 :(得分:1)

在你的JS小提琴中,这是因为你的foreach与人类绑定......不是为了排序的人。

第一次排序的原因是因为计算运行了一次......但是没有订阅。

但是,由于对基础数组进行了一些订阅,因此当您使用括号时,计算结果会再次运行。

编辑:

使用括号时,在调用observable时,computed会订阅数组。订阅项目更改时,将重新执行计算。