【问题标题】:Knockout Filtering on Observable Array可观察数组上的剔除过滤
【发布时间】:2014-01-18 09:42:17
【问题描述】:

我已经开始学习 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);
}

【问题讨论】:

    标签: javascript knockout.js filter observable


    【解决方案1】:

    您不能在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会在解析绑定时执行你的函数,而不是在你点击时按钮。

    【讨论】:

    • 感谢您的回复,但我仍然无法使过滤器正常工作。我将 'return prod.genre = currentFilter() 更改为 return ... self.currentFilter() 因为它引发了错误。否则,不会引发错误,产品列表不会更新。另外,在点击绑定周围添加 function(){} 的原因是什么?谢谢。
    • @SkelDave 是的,self.currentFilter() 是一个错字。但是您不仅需要返回,还需要编写 return prod.genre == self.currentFilter(); 单个 = 是分配,而双 == 是相等检查。我添加了一个工作示例以及对function(){} 的一些解释
    • 谢谢,问题已经解决了!
    【解决方案2】:

    首先你误解/使用computed Observables。来自KnockoutJS documentation

    这些函数依赖于一个或多个其他函数 observables,并且会在任何时候自动更新 依赖关系改变。

    您计算的 observable filterProducts 依赖于 observable 数组 products,您不会更改,您只需读取它的值。因此,无需通知filterProducts 进行重新评估。

    那么,什么是快速简单的解决方法?

    1. 定义一个新的可观察对象filteredGenre,您的filterProducts 将依赖该对象。
    2. 更改 filterProducts 以检查 filteredGenre 的值并根据它返回过滤后的产品。
    3. 更改filter 函数,以便当它获得新的genre 时,它会更改filteredGenre,这将导致重新评估计算的filterProducts

    我希望你明白了。

    【讨论】:

    • 感谢您澄清要点,我也误解了计算 Observables。我在实施过程中遵循了您的指示,按预期工作。
    【解决方案3】:

    您可能想看看原始淘汰赛作者的Knockout Projections 插件。它在大型集合的场景中具有性能优势。详情请见blogpost

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多