【问题标题】:Knockoutjs: how to filter a foreach binding without using ifKnockoutjs:如何在不使用 if 的情况下过滤 foreach 绑定
【发布时间】:2013-04-16 01:50:23
【问题描述】:

有没有办法使用自定义绑定来实现以下语句,以消除 if 绑定:

<div data-bind="foreach: $root.customersVM.customers">
    @Html.Partial("_Customer")
    <div data-bind="foreach: $root.ordersVM.orders">
        <!-- ko if: customer() == $parent.id() -->
        @Html.Partial("_Order")
        <!-- /ko -->
    </div>
</div>

或者换一种说法:有人知道Knockout.js foreach: but only when comparison is true的答案中的方式2吗?

【问题讨论】:

  • @Sergio:如果有很多缺点,我正在努力消除这些缺点。见:link
  • @user1252580:去过那里,但没有回答我的问题
  • 我很困惑为什么会有客户循环访问,然后订单是针对任何客户的。为什么不在同一个 json 中获取客户和他们的订单,那么这不是问题?
  • @John:这个例子当然是简化的。它涉及具有单独 ViewModel 的单独数据库表。我认为自定义绑定,比如foreachFiltered,将是我问题的最佳答案。

标签: javascript knockout.js


【解决方案1】:

如何创建另一个计算或函数来执行过滤并且您可以迭代而不是迭代订单?

HTML

<div data-bind="with: filteredCustomers('smith')">
    <span data-bind="text: name"></span>
</div>

<div data-bind="foreach: customers">
    <span data-bind="text: name"></span>
</div>

<div data-bind="foreach: filteredOrders(4)">
    <span data-bind="text: id"></span>
</div>

<div data-bind="foreach: orders">
    <span data-bind="text: id"></span>
</div>

<button data-bind="click: function() {customers.push({name:'Smith'});}">Add customer</button>
<button data-bind="click: function() {orders.push({id:4});}">Add order</button>

Javascript:

var vm = {
    customers: ko.observableArray([
        {name: 'Smith'}, {name: 'Williams'}, {name: 'Brown'}, {name: 'Miller'}
    ]),
    orders: ko.observableArray([
        {id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 4}
    ])
};

// return first hit (unique ID)
vm.filteredCustomers = function(name) {
   return ko.utils.arrayFirst(this.customers(), function(customer) {
      return (customer.name.toLowerCase() === name.toLowerCase());
   });
};

// return all hits
vm.filteredOrders = function(id) {
   return ko.utils.arrayFilter(this.orders(), function(order) {
      return (order.id === id);
   });
};

ko.applyBindings(vm);

【讨论】:

  • 是的,这通常可以工作(使用ko.utils.arrayFilter),但是客户和订单来自不同的视图模型(示例代码已简化)。那么我将计算函数放在哪里(在哪个模型中)以及如何传递过滤器或id?
  • 我不确定该函数的放置位置,但可能在您当前迭代的任何视图模型中。至于传递参数,请参见此小提琴示例:jsfiddle.net/FRzbM
  • 感谢 jsfiddle。仍然希望有一个通用的foreachFiltered 绑定,但我会再试一次你的解决方案。
  • 以 Tuan 的解决方案为起点,我创建了一个更新的小提琴:jsfiddle.net/nYbpE。大多数时候我都有一个唯一的 ID,所以我为此使用了ko.utils.arrayFirst。当可以返回多个结果时,我也使用ko.utils.arrayFilter 而不是map
【解决方案2】:

我认为您对性能的最佳选择是从 2 个不同的数据库中获取数据并将它们放在同一个视图模型中。例如,在您的 javascript 视图模型中,首先抓住客户。然后抢订单。为每个客户添加一个 orders 属性,并为其添加一个 orders 可观察数组。

您的视图模型旨在供视图使用。因此,最好获取数据,无论它是什么罪,并使其适用于视图。正如您所提到的,“如果”可能是一个性能问题。此外,如果您按照评论中的建议在函数中使用 foreach ,那么当可观察数组发生更改时,它会不必要地循环遍历项目。我更喜欢先让我的视图模型井井有条,然后用户交互很快。

2 美分 :)

【讨论】:

    猜你喜欢
    • 2014-12-31
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-29
    • 2023-02-04
    • 1970-01-01
    相关资源
    最近更新 更多