我有一个html section元素,它有一个Knockout foreach绑定到我的viewmodel上的一组项目。这可以很好地将集合中的每个项目渲染到垂直向下的div上。我现在希望项目根据窗口大小按行分组,因此项目在桌面浏览器上显示为4行,但在移动设备上每行只显示1行。
我实际上是通过在viewmodel中创建组并让我的view元素与foregroup属性绑定来实现的。这种方法的问题在于我的viewmodel现在具有我认为的一堆视图逻辑并直接引用window对象。哪个不对,我不认为。
我已经有一个单独的js文件,其中包含视图特定的逻辑,即“slideVisible”之类的自定义Knockout绑定。如何将分组逻辑从我的viewmodel移到此文件中?我猜我如果在viewmodel中没有进行分组,我将无法使用Knockout的foreach绑定?
答案 0 :(得分:4)
如果你需要在KO中动态地执行此操作,那么这里是一个绑定普通foreach
绑定的绑定示例,并动态创建一个计算结果,该计算结果返回一个带有行/列的结构,基于“算“可观察。
ko.bindingHandlers.foreachGroups = {
init: function(element, valueAccessor) {
var groupedItems,
options = valueAccessor();
//create our own computed that transforms the flat array into rows/columns
groupedItems = ko.computed({
read: function() {
var index, length, group,
result = [],
count = +ko.utils.unwrapObservable(options.count) || 1,
items = ko.utils.unwrapObservable(options.data);
//create an array of arrays (rows/columns)
for (index = 0, length = items.length; index < length; index++) {
if (index % count === 0) {
group = [];
result.push(group);
}
group.push(items[index]);
}
return result;
},
disposeWhenNodeIsRemoved: element
});
//use the normal foreach binding with our new computed
ko.applyBindingsToNode(element, { foreach: groupedItems });
//make sure that the children of this element are not bound
return { controlsDescendantBindings: true };
}
};
您可以使用它:
<div data-bind="foreachGroups: { data: items, count: count }">
<ul data-bind="foreach: $data">
<li data-bind="text: $data"></li>
</ul>
</div>
以下是一个示例:http://jsfiddle.net/rniemeyer/F48XU/
对于你的具体情况,我可能会:
count
选项,然后传入商品count
函数中创建自己的init
observable。resize
事件处理程序,并相应地更新count
observable。它可能看起来像(填写你特定的调整大小逻辑):
ko.bindingHandlers.foreachGroups = {
init: function(element, valueAccessor) {
var groupedItems,
data = valueAccessor(),
count = ko.observable(1);
ko.utils.registerEventHandler(window, "resize", function() {
//run your calculation logic here and update the "count" observable with a new value
});
//create our own computed that transforms the flat array into rows/columns
groupedItems = ko.computed({
read: function() {
var index, length, group,
result = [],
itemsPerRow = +ko.utils.unwrapObservable(count) || 1,
items = ko.utils.unwrapObservable(data);
//create an array of arrays (rows/columns)
for (index = 0, length = items.length; index < length; index++) {
if (index % itemsPerRow === 0) {
group = [];
result.push(group);
}
group.push(items[index]);
}
return result;
},
disposeWhenNodeIsRemoved: element
});
//use the normal foreach binding with our new computed
ko.applyBindingsToNode(element, { foreach: groupedItems });
//make sure that the children of this element are not bound
return { controlsDescendantBindings: true };
}
};