gpt4 book ai didi

javascript - Knockout.js:使用带有映射插件的嵌套可观察量

转载 作者:行者123 更新时间:2023-11-28 02:29:02 25 4
gpt4 key购买 nike

我正在构建一个侧边栏来过滤主视图,例如 John Lewis 中的侧边栏。我的代码可以工作,但它并不漂亮。

我知道有几个类似的问题,但我无法完全理解我自己的用例。

我需要从服务器获取复选框的名称(例如通过 JSON),以便在我的 ShopView 上动态创建 observableArrays。

具体情况如下:

var data = {
'gender' : [ ],
'color' : [ ]
};

var filterMapping = {
create: function( obj ) {
return ko.observableArray( obj.data );
}
}

var ShopView = new function() {

var self = this;

ko.mapping.fromJS( { filters: data }, filterMapping, self );

// this is the bit I don't like
this.filterChange = ko.computed(function () {
for( var key in self.filters ) {
var obj = self.filters[key];
if( ko.isObservable(obj)){
obj();
}
}
});

this.filterChange.subscribe( function( ) {
//make AJAX request for products using filter state
});

}

我的 HTML 看起来如您所料:

性别

    <ul>
<li><input type="checkbox" value="male" data-bind="checked: filters.gender" />Male</li>
<li><input type="checkbox" value="female" data-bind="checked: filters.gender" />Female</li>
</ul>

正如我所说,它可以工作,但不太好。在理想的世界中,我可以订阅 this.filters,例如

this.filters.subscribe( function() { 
//make AJAX request for products using filter state
});

注意我不想在客户端进行过滤 - 只是在动态绑定(bind)的复选框发生变化时更新我的​​ View 模型。

有什么想法吗?谢谢!

最佳答案

首先,映射插件应该被视为代码重复的辅助工具。我认为将映射插件本身视为一个解决方案并不是一个好主意;至少不是直接的。它还掩盖了当您在 SO 上发布代码时发生的情况,因为我们看不到您正在使用的模型。只是一个想法。

现在,如果您想从服务器获取动态过滤器,并使用它们来过滤项目列表(就像在商店中一样),我会这样做(这里是 the fiddle ):

var FilterOption = function(name) {
this.name = name;
this.value = ko.observable(false);
};

var Filter = function(data) {
var self = this;
self.name = data.name;
options = ko.utils.arrayMap(data.options, function(o) {
return new FilterOption(o);
});
self.options = ko.observableArray(options);
self.filteredOptions = ko.computed(function() {
var options = []
ko.utils.arrayForEach(self.options(), function(o) {
if (o.value()) options.push(o.name);
});
//If no options, false represents no filtering for this type
return options.length ? options : false;
});
};

var ViewModel = function(data) {
var self = this;
self.items = ko.observableArray(data.items);
filters = ko.utils.arrayMap(data.filters, function(i) {
return new Filter(i);
});
self.filters = ko.observableArray(filters);
self.filteredItems = ko.computed(function() {
//Get the filters that are actually active
var filters = ko.utils.arrayFilter(self.filters(), function(o) {
return o.filteredOptions();
});
//Remove items that don't pass all active filter
return ko.utils.arrayFilter(self.items(), function(item) {
var result = true;
ko.utils.arrayForEach(filters, function(filter) {
var val = item[filter.name.toLowerCase()];
result = filter.filteredOptions().indexOf(val) > -1;
});
return result;
});
});
};

下一个明显的步骤是添加对具有多个属性或选项属性的项目的支持,但这应该为您提供基本的想法。您有一个过滤器列表,每个过滤器都有任意数量的选项(可相加地堆叠),并且您使用计算项数组来存储过滤项的结果。

<小时/>

编辑:要使用 ajax 订阅获取项目,您可以将 FilteredItems 属性替换为获取所选过滤器的计算属性,然后订阅它,例如这个:

var ViewModel = function(data) {
var self = this;
self.items = ko.observableArray(data.items);
filters = ko.utils.arrayMap(data.filters, function(i) {
return new Filter(i);
});
self.filters = ko.observableArray(filters);
self.selectedFilters = ko.computed(function() {
ko.utils.arrayFilter(self.filters(), function(o) {
return o.filteredOptions();
});
});
self.selectedFilters.subscribe(function() {
//Ajax request that updates self.items()
});
};

关于javascript - Knockout.js:使用带有映射插件的嵌套可观察量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14483780/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com