简体   繁体   English

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

[英]Knockoutjs: how to filter a foreach binding without using if

Is there a way to implement the statements below using a custom binding, to eliminate the if-binding: 有没有办法使用自定义绑定实现下面的语句,以消除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>

Or put it in another way: Does someone know Way 2 in the answer to Knockout.js foreach: but only when comparison is true ? 或者以另一种方式说:在Knockout.js foreach的答案中有人知道Way 2 :但只有当比较为真时

How about creating another computed or function that does the filtering and that you can iterate over instead of iterating over orders? 如何创建另一个执行过滤的计算机或函数,并且可以迭代而不是迭代订单?

HTML 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: 使用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);

I think your best bet on performance would be to take the data from 2 different databases and put them together in the same viewmodel. 我认为你在性能上最好的选择是从两个不同的数据库中获取数据并将它们放在同一个视图模型中。 For example, in your viewmodel in javascript, grab the customers first. 例如,在javascript中的viewmodel中,首先抓住客户。 Then grab the orders. 然后抓住订单。 Add an orders property to each customer and add an orders observablearray to it. 向每个客户添加一个订单属性,并向其添加一个observablearray订单。

Your viewmodel is intended for use by the view. 您的viewmodel旨在供视图使用。 So its best to take the data, however it come sin, and make it work for the view. 所以最好采取数据,但它会犯罪,并使其适用于视图。 As you mention, the "if" will likely be a perf issue. 如你所述,“if”可能是一个性能问题。 Also, if you use a foreach in a function as you suggest in your comment it is needlessly looping through items when the observable arrays change. 此外,如果您在注释中使用foreach函数,则在可观察数组发生更改时,它会不必要地循环遍历项目。 I prefer to get my viewmodel in order first, then the user interactions are fast. 我更喜欢先按顺序获取我的viewmodel,然后用户交互很快。

2 cents :) 2美分:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM