7

我有一个对象数组,它们连接到一个淘汰赛可观察数组中。我需要对这些数组应用排序,我遇到了一些有点令人困惑的行为。

我的第一次尝试涉及在 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 数组之间的差异,但我很难概念化为什么行为会发生变化。我能够让它工作,但我也很好奇什么被认为是最佳实践。

谢谢你的帮助。:)

4

2 回答 2

2

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

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

items.slice(0).sort()

更详细地看
https://github.com/knockout/knockout/issues/1380

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

于 2015-02-02T09:55:03.683 回答
1

在您的 JS Fiddle 中,这是因为您的 foreach 与人绑定......而不是 sortedPeople。

它第一次排序的原因是因为计算运行一次......但不订阅。

但是,由于对底层数组的某些订阅,当您使用括号时,计算最终会再次运行。

编辑:

当您使用括号时,在调用 observable 时,computed 订阅数组。当订阅的项目发生变化时,重新执行计算。

于 2014-01-21T20:35:04.453 回答