我正在使用Knockout自定义绑定处理程序(从Creating groups with Knockout.js foreach借用)。在嵌套标记中,我想引用位于视图模型根目录的observable。但是绑定失败,因为$ root未定义。相同的标记与标准的foreach绑定一起工作正常。我不知道为什么自定义处理程序会阻止使用$ root。
以下是绑定处理程序的来源:
ko.bindingHandlers.foreachGrouped = {
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 };
}
};
这是html标记:
Header Text: <input data-bind="value: header" />
Group count: <input data-bind="value: count" />
<div data-bind="foreachGrouped: { data: items, count: count }">
<h1 data-bind="html: $root.header"></h1>
<ul data-bind="foreach: $data">
<li data-bind="text: $data"></li>
</ul>
</div>
以下是用于连接视图模型的代码:
ko.applyBindings({
header: ko.observable("Group Header"),
items: ko.observableArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
count: ko.observable(4)
});
答案 0 :(得分:3)
问题是原始的bindingContext在处理程序中丢失了。所以当调用ko.applyBindingsToNode()
时,它会使用一个全新的上下文(它是空的)。处理程序在能够指定绑定上下文的时间之前就已经过时了,它是在更高版本的knockout中添加的。您需要对处理程序进行调整才能保留该上下文。
ko.applyBindingsToNode(element, { foreach: groupedItems }, bindingContext);
所以你需要在处理程序中进行调整(删除不相关的位以便更容易看到):
ko.bindingHandlers.foreachGrouped = {
// need to get the binding context (fifth param)
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
//...
//use the normal foreach binding with our new computed
ko.applyBindingsToNode(element, { foreach: groupedItems }, bindingContext); // pass in the binding context
//...
}
};