Mvvm 使用Knockout.js foreach创建组
我有一个html节元素,它有一个Knockout-foreach绑定到viewmodel上的一个项目集合。这可以很好地将集合中的每个项呈现到垂直向下的div上。现在,我希望项目根据窗口大小按行分组,这样项目在桌面浏览器上显示为4行,但在移动设备上每行仅显示1行 实际上,我是通过在viewmodel中创建组并使用foreach将我的视图元素绑定到此groups属性来实现这一点的。这个方法的问题是,我的View模型现在有了我将要考虑的一组视图逻辑,并直接引用窗口对象。我认为这是不对的Mvvm 使用Knockout.js foreach创建组,mvvm,knockout.js,Mvvm,Knockout.js,我有一个html节元素,它有一个Knockout-foreach绑定到viewmodel上的一个项目集合。这可以很好地将集合中的每个项呈现到垂直向下的div上。现在,我希望项目根据窗口大小按行分组,这样项目在桌面浏览器上显示为4行,但在移动设备上每行仅显示1行 实际上,我是通过在viewmodel中创建组并使用foreach将我的视图元素绑定到此groups属性来实现这一点的。这个方法的问题是,我的View模型现在有了我将要考虑的一组视图逻辑,并直接引用窗口对象。我认为这是不对的 我已经有了一个
我已经有了一个单独的js文件,其中包含特定于视图的逻辑,即“slideVisible”之类的自定义敲除绑定。如何将分组逻辑移出viewmodel并移到此文件中?我猜如果分组没有在viewmodel中完成,我将无法使用Knockout的foreach绑定?如果需要在KO中动态执行此操作,那么下面是一个绑定示例,它包装了正常的foreach绑定,并创建了一个动态计算的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 };
}
};
如果需要在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 };
}
};
注意,给定形式的解决方案将在分组时创建一个新的绑定上下文,因此$root和父上下文将变得未定义。查看上的答案以查看保留原始绑定上下文的修改。请注意,给定形式的解决方案将在分组时创建新的绑定上下文,因此$root和父上下文将变得未定义。查看上的答案,查看保留原始绑定上下文的修改。
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 };
}
};