繁体   English   中英

可观察数组上的Knockout过滤

[英]Knockout Filtering on Observable Array

我已经开始学习Knockout了,我在按钮点击过滤可观察数组并显示结果时遇到了一些麻烦。

这是我的模特:

function Product(data) {     
    this.id = data.id;
    this.name = data.name;
    this.price = data.price;
    this.description = data.desc;
    this.image = data.image;
    this.genre = data.genre;
    this.show = data.show;
    this.offer_desc = data.offer_desc;
    this.offer_id = data.offer_id;
}

function ProductModel() {
    var self = this;
    self.products = ko.observableArray([]);

    $.getJSON('../PHP/Utilities.php?json=true', function(json) {
       var mappedProducts = $.map(json, function(item) { return new Product(item) });
       self.products(mappedProducts);
    });

    self.filterProducts = ko.computed(function(genre) {
        if(typeof genre === 'undefined') {
            return self.products(); //initial load when no genre filter is specified
        } else {
            return ko.utils.arrayFilter(self.products(), function(prod) {
                return prod.genre = genre;
            });
        }
    });
}

ko.applyBindings(new ProductModel());

这是html:

<div data-bind="foreach: filterProducts">
    <div class="row">
        <div class="col-md-2">
        <img data-bind="attr:{src: '../images/' + image, alt: name}" />
        </div>
        <div class="col-md-2" data-bind="text: name"></div>
        <div class="col-md-1" data-bind="text: price"></div>
        <div class="col-md-3" data-bind="text: description"></div>
        <div class="col-md-1" data-bind='text: offer_id'>                  
        <div class="col-md-2" data-bind="text: genre"></div>
        <div class="col-md-1" data-bind="text: show"></div>
    </div>
</div>

我也不确定如何绑定点击功能来过滤类型上的产品。 我认为这样的事情......但它不起作用

<button data-bind="click: filter('1')"> Filter </button>

self.filter = function(genre) {
    self.filterProducts(genre);
}

你不能在ko.computed有一个带参数的ko.computed

您需要的是将当前过滤器存储在新属性中并在计算中使用它

function ProductModel() {
    var self = this;
    self.products = ko.observableArray([]);

    self.currentFilter = ko.observable(); // property to store the filter

    //...

    self.filterProducts = ko.computed(function() {
        if(!self.currentFilter()) {
            return self.products(); 
        } else {
            return ko.utils.arrayFilter(self.products(), function(prod) {
                return prod.genre == self.currentFilter();
            });
        }
    });
}

在您的click处理程序中,只需设置当前过滤器:

<button data-bind="click: function() { filter('1') }"> Filter </button>

self.filter = function(genre) {
    self.currentFilter(genre);
}

演示JSFiddle

如果你想在click绑定中传递额外的参数a(参见文档中 ),请注意function() { } ,否则Knockout会在解析绑定时执行你的函数,而不是在你点击按钮时执行。

首先,你误解/使用computed Observables 来自KnockoutJS文档

这些是依赖于一个或多个其他可观察对象的函数,并且只要这些依赖关系中的任何一个发生更改,它们就会自动更新。

您计算的可观察filterProductsproducts依赖于您不会更改的可观察数组products ,您只需读取它的值即可。 因此,没有任何内容可以通知filterProducts进行重新评估。

那么,什么是快速简单的修复?

  1. 定义filterProducts将依赖的新的可观察对象filteredGenre
  2. 更改filterProducts以便检查filteredGenre的值并基于它返回过滤后的产品。
  3. 更改filter功能,以便在获得新genre时更改filteredGenre ,这将导致重新评估计算的filterProducts

我希望你有这个主意。

您可能想看看原始淘汰赛作者的Knockout Projections插件。 它在具有大型集合的场景中具有性能优势。 有关详细信息,请参阅blogpost

self.filterProducts = self.products.filter(function(prod) {
    return !self.currentFilter() || prod.genre == self.currentFilter();
});

暂无
暂无

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

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