Javascript Knockoutjs:如何在不使用if的情况下过滤foreach绑定

Javascript Knockoutjs:如何在不使用if的情况下过滤foreach绑定,javascript,knockout.js,Javascript,Knockout.js,是否有一种方法可以使用自定义绑定实现以下语句,以消除if绑定: <div data-bind="foreach: $root.customersVM.customers"> @Html.Partial("_Customer") <div data-bind="foreach: $root.ordersVM.orders"> <!-- ko if: customer() == $parent.id() --> @H

是否有一种方法可以使用自定义绑定实现以下语句,以消除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>

@Html.Partial(“\u Customer”)
@Html.部分(“_顺序”)

或者换一种方式:有人知道答案中的方法2吗?

创建另一个执行过滤的计算函数或函数,您可以迭代,而不是迭代顺序

HTML


我认为最好的性能选择是从两个不同的数据库获取数据,并将它们放在同一个viewmodel中。例如,在javascript的viewmodel中,首先抓取客户。然后拿到订单。向每个客户添加orders属性,并向其添加orders observablearray

视图模型是供视图使用的。因此,最好是获取数据,不管数据如何,并使其适用于视图。正如您提到的,“如果”很可能是性能问题。此外,如果您在函数中使用foreach,正如您在注释中所建议的那样,那么当可观察数组发生变化时,它将不必要地在项目之间循环。我更喜欢先整理好我的viewmodel,然后用户交互会很快


2美分:)

试试看,这对你很有用。@Sergio:if有很多缺点,我正在努力消除这些缺点。请看:@user1252580:belie,但它没有回答我的问题。我不明白为什么你会有你正在循环的客户,那么订单是针对任何客户的。为什么不让客户和他们的订单使用同一个json,那么这就不是问题了?@John:这个例子当然简化了。它涉及具有独立视图模型的独立数据库表。我认为定制绑定,比如说
foreachfilter
,将是我问题的最佳答案。是的,这通常会起作用(使用
ko.utils.arrayFilter
),但是客户和订单来自不同的视图模型(示例代码已简化)。那么,我应该将计算出的函数放在哪里(在哪个模型中)以及如何传递过滤器或id呢?我不确定该将函数放在哪里,但可能放在您当前迭代的哪个viewmodel中。至于传递一个参数,请参见这个提琴示例:感谢JSFIDLE。仍然希望有一个通用的
foreachFiltered
绑定,但我会给你的解决方案再试一次。使用Tuan的解决方案作为起点,我创建了一个更新的fiddle:。大多数时候我都有一个唯一的ID,所以我使用了
ko.utils.arrayFirst
。当可以返回多个结果时,我也使用
ko.utils.arrayFilter
而不是
map
<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>
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);