Knockout - 使用foreach和sort组合

20

我在将foreach绑定与排序结合时遇到了麻烦。我有一个列表像这样绑定:

<article data-bind="foreach: widgets">  

Widgets是一个简单的可观察数组:

var widgets= ko.observableArray();

这个很好用,可以给我列出我的“小部件”清单。如果我添加新的“小部件”,则通过数据绑定会动态地出现在清单中。

但是,一旦我对数组添加排序功能:

<article data-bind="foreach: widgets.sort(function (left, right) { return left.order() == right.order() ? 0 : (left.order() < right.order() ? -1 : 1); })">

新添加的小部件不再出现在我的列表中 - 除非我重新加载页面。(此时排序运作得很好 - 如果我更新正在排序的“顺序”字段,则列表中的项目会动态重新排序)。

我该如何让排序与可观察数组中新项目的动态更新良好地协同工作?

为了检索我的数据,我使用Breezejs,但我不认为它会影响到这种情况。

1个回答

36
observableArray.sort 返回经过排序的基础数组("regular" array),而不是一个 observableArray,因此更改不会在UI上显示。
想要进行排序并更新UI,需要创建一个 ko.computed 来进行排序,并在绑定中使用该计算属性。因为 ko.computed 会监听 widgets 的变化并重新计算排序结果。
var widgets= ko.observableArray();

var sortedWidgets = ko.computed(function() {
   return widgets().sort(function (left, right) { 
        return left.order() == right.order() ? 
             0 : 
             (left.order() < right.order() ? -1 : 1); 
   });
});

然后您可以将其绑定:

<article data-bind="foreach: sortedWidgets" />

谢谢 - 那个很好地解决了问题。你能否更新你的答案,在 ko.computed 的开头加上 "function ()"(在第一个括号内)?然后我会接受它作为答案。 - daveywc
根据您上面的回答,我如何使嵌套的foreach工作,例如在我的顶级列表中的一个小部件的导航属性上进行foreach。在这种情况下,我没有明确声明我要绑定的observable数组,因此我看不到如何使用这种方法。 - daveywc
我已经修复了我的回答中的拼写错误。虽然我不熟悉Breezejs,但我认为它可以配置为为您创建这些自定义排序属性。无论如何,JS是动态的,因此您可以向任何已经存在的对象添加新属性。 - nemesv
1
我通过在自定义构造函数中为我的Breeze实体添加Knockout计算属性,成功地使得嵌套的foreach排序功能在导航属性上运行 - 请参考http://www.breezejs.com/documentation/extending-entities。 - daveywc
@daveywc,您能否提供一个示例,说明您在使用排序时如何实现这一点? - PW Kad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接