【问题标题】:Knockout Observable Array Unexpected Sorting淘汰 Observable 数组意外排序
【发布时间】:2017-07-13 07:56:20
【问题描述】:

背景: 我目前正在开发使用 Knockout 的 UI。我一直在使用淘汰赛一段时间,但这个问题让我很难过。我正在尝试对一个名为 Actions 的可观察数组进行排序,并将其绑定到我创建的模板中的 foreach。我通过创建一个调用 Actions 数组上的排序函数的计算来进行绑定。

代码:

self.Actions = ko.observableArray([]);

self.SortedActions = ko.computed(function() {
return self.Actions()
    .sort(function (a, b) {
        var aOrder = Number(a.Order());
        var bOrder = Number(b.Order());

        return aOrder < bOrder ? 1 : -1;
    });
});

<div class="row" data-bind="template: { name: 'action-template', foreach: SortedActions }"></div>

预期结果: 我试图让数组从 1-n 中的每个动作中对 Order observable 进行排序。我已经知道没有重复订单,所以这不是问题,而且我知道所有内容都是从 1 开始到 n 结束的整数。

实际结果: 当 Actions 的长度小于 10 时,一切似乎都在工作。但是,一旦大于 10,订单就不会像我预期的那样出现。每次我加载它们时,它们都会以相同的顺序出现,但是该顺序不正确且看似随机。 (这意味着它似乎没有对明显的模式进行排序。例如,按字母顺序)

如果有人对为什么这不起作用有任何想法,我将不胜感激。我以前从未见过这种行为如此奇怪,我完全被难住了。如果您需要更多详细信息,请告诉我。这是我的第一篇文章,所以我可能搞砸了。

谢谢, :)

【问题讨论】:

  • 有几件事:sort 作用于原始数组,因此也会导致self.Actions 被排序。您应该使用return bOrder - aOrder; 来获得正确的结果。
  • 你是否试图实现一个始终处于排序状态的数组?
  • 是的,我想要一个总是排序显示的数组。这样,当我重新排序操作时,我需要做的就是更改订单号。
  • @MichaelBest 这对我也不起作用。这目前给了我 [8, 1, 7, 14, 12, 11, 10, 9, 2, 13, 6, 5, 4, 3, 15, 16] 的顺序
  • 切换我的 1 和 -1 似乎可以解决问题。我还想指出,这个列表有点递归,所以实际上需要进行一些更改,但目前一切都按预期工作,排序集为 aOrder

标签: javascript arrays sorting knockout.js data-binding


【解决方案1】:

当 observable 发生这样的变化时,您可以使用订阅对初始数组进行排序。

请注意,这将对每次更改进行排序,因此,如果您将大量添加直接批量添加到可观察对象,这将是非常浪费的。您应该添加到底层数组,然后调用valueHasMutated()

如果你最终这样做了,你也可以在需要时对数组调用 sort,这样会更清晰。

var viewModel = function(){
  var self = this;
  self.Actions = ko.observableArray(["one", "two", "three"]);

  self.Actions.subscribe(function() {
    console.log("sorting ...");
    self.Actions().sort();
  });
  
  // trigger sorting
  self.Actions.push("zero");
  
  self.addnew = function(){
    self.Actions.push("new" + self.Actions().length);
  }
}

ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<ol data-bind="foreach: Actions">
  <li data-bind="text: $data"></li>
</ol>

<button data-bind="click: addnew">Add new</button>

【讨论】:

    猜你喜欢
    • 2013-04-10
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 1970-01-01
    • 2013-05-15
    • 2012-11-14
    相关资源
    最近更新 更多