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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9968283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 08:22:54  来源:igfitidea点击:

Knockoutjs: how to filter a foreach binding without using if

javascriptknockout.js

提问by mhu

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 2in the answer to Knockout.js foreach: but only when comparison is true?

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

回答by Tuan

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);

回答by John Papa

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. Then grab the orders. Add an orders property to each customer and add an orders observablearray to it.

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

Your viewmodel is intended for use by the view. 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. 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. I prefer to get my viewmodel in order first, then the user interactions are fast.

您的视图模型旨在供视图使用。所以最好的方法是获取数据,不管它是怎么来的,并让它为视图工作。正如您所提到的,“如果”可能是性能问题。此外,如果您按照评论中的建议在函数中使用 foreach,则当可观察数组更改时,它会不必要地循环遍历项目。我更喜欢先让我的视图模型按顺序排列,然后用户交互很快。

2 cents :)

2 美分 :)