Ske*_*ave 41 javascript filter observable knockout.js
我已经开始学习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());
Run Code Online (Sandbox Code Playgroud)
这是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>
Run Code Online (Sandbox Code Playgroud)
我也不确定如何绑定点击功能来过滤类型上的产品.我认为这样的事情......但它不起作用
<button data-bind="click: filter('1')"> Filter </button>
self.filter = function(genre) {
self.filterProducts(genre);
}
Run Code Online (Sandbox Code Playgroud)
nem*_*esv 54
你不能拥有一个带有参数的函数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();
});
}
});
}
Run Code Online (Sandbox Code Playgroud)
在你的click处理程序中只需设置当前过滤器:
<button data-bind="click: function() { filter('1') }"> Filter </button>
self.filter = function(genre) {
self.currentFilter(genre);
}
Run Code Online (Sandbox Code Playgroud)
演示JSFiddle
注意function() { }需要,如果你想传递额外的参数一中click结合(也看到了在文档),否则当它解析淘汰赛将执行你的函数的结合,而不是当你点击的按钮.
首先,您会误解/使用computed Observables。从KnockoutJS文档中:
这些是依赖于一个或多个其他可观察对象的函数,只要这些依赖项中的任何一个发生更改,它们就会自动更新。
您计算的可观察值filterProducts取决于products您未更改的可观察数组,您只需读取其值即可。因此,没有任何filterProducts要重新评估的通知。
那么,什么是快速简单的解决方法?
filteredGenre您filterProducts将依赖的新可观察对象。filterProducts,以使其检查和的值,filteredGenre并返回过滤后的产品。filter函数,以便在获取新函数时进行genre更改filteredGenre,这将导致重新计算计算值filterProducts我希望你有主意。
您可能想看看原始淘汰赛作者的Knockout Projections插件.它在具有大型集合的场景中具有性能优势.有关详细信息,请参阅blogpost.
self.filterProducts = self.products.filter(function(prod) {
return !self.currentFilter() || prod.genre == self.currentFilter();
});
Run Code Online (Sandbox Code Playgroud)