【问题标题】:Sort Knockout's computed only once in data-bind foreachSort Knockout 在数据绑定 foreach 中只计算一次
【发布时间】:2025-12-28 14:35:12
【问题描述】:

所以这里我的问题是我希望淘汰赛的 foreach 根据每个对象的一个​​值(order 的总 TTC)以降序显示我计算的对象数组。而且我不希望这个订单改变,即使当用户改变东西时订单中的totalTTC也会改变。但是每次进行更改时排序都会更新,我不知道如何禁用它。这是我的计算:

appViewModel.orders = ko.computed(() -> (
  orders = []
  # Check if seller of this shoppingCartLine exists
  appViewModel.shoppingCartLines().forEach((shoppingCartLine) ->
  existingOrder = null
  orders.forEach((order) ->
    if order.seller? and order.seller.id() == shoppingCartLine.ad.ownerJson.id()
      existingOrder = order
  )
  # If it exits add it to its shoppingCartLines array
  if existingOrder?
    existingOrder.shoppingCartLines.push(shoppingCartLine)
    return
  # Otherwise create a new order from this shoppingCartLine
  else
    seller = shoppingCartLine.ad.ownerJson
    shoppingCartLines = ko.observableArray([shoppingCartLine])

    order = new Order(seller, shoppingCartLines, appViewModel.freeShippingFeesThreshold)
    orders.push(order)
    return
  )
  return orders
))

这是我的html:

<div data-bind="foreach: {data: orders().sort(function (o, r) { return r.totalHT() > o.totalHT() ? 1 : -1 }), as: 'order'}">

我只想触发一次排序功能。

【问题讨论】:

  • 当添加/删除订单时,您是否淘汰了 foreach 以进行更新?如果没有,您可能只是不为此使用可观察对象。
  • 我该怎么做?
  • 只需将排序函数从绑定中取出,在数组填满后手动调用一次即可。

标签: knockout.js computed-observable


【解决方案1】:

由于您说添加/删除订单时不需要更新淘汰赛,也不需要更新排序,因此订单不需要是可观察的。

我个人也会在 viewModel 中对其进行排序。我喜欢标记尽可能少地包含代码。

  appViewModel.orders = computeOrders().sort(function (o, r) { return r.totalHT() > o.totalHT() ? 1 : -1 });

  function computeOrders() {
      # Check if seller of this shoppingCartLine exists
      appViewModel.shoppingCartLines().forEach((shoppingCartLine) ->
      existingOrder = null
      orders.forEach((order) ->
        if order.seller? and order.seller.id() == shoppingCartLine.ad.ownerJson.id()
          existingOrder = order
      )
      # If it exits add it to its shoppingCartLines array
      if existingOrder?
        existingOrder.shoppingCartLines.push(shoppingCartLine)
        return
      # Otherwise create a new order from this shoppingCartLine
      else
        seller = shoppingCartLine.ad.ownerJson
        shoppingCartLines = ko.observableArray([shoppingCartLine])

        order = new Order(seller, shoppingCartLines, appViewModel.freeShippingFeesThreshold)
        orders.push(order)
        return
      )
      return orders
  }

HTML:

<div data-bind="foreach: orders">

【讨论】:

  • 我已经尝试过了,但它不起作用。最初不是我的代码。我只是在工作中对现有代码添加一些更改,显然它必须保持可淘汰的可观察性,否则它会在编译时不断向我抛出错误。
  • 尽量保持它可观察,而不是计算。这不会产生错误,也不会重新排序数组:appViewModel.orders = ko.observable(computeOrders().sort(function (o, r) { return r.totalHT() &gt; o.totalHT() ? 1 : -1 }));