我能想到的最好的方法是创建专门的绑定来存储有关数组和当前项目的上下文信息。
公开有关数组的上下文的自定义foreach
绑定:
ko.bindingHandlers.xforeach = (function() {
var createContext = function(array) {
return {
'$array': array,
'$arrayLength': function() { return ko.unwrap(array).length; }
};
};
return {
init: ko.bindingHandlers.foreach.init,
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var extendedContext = createContext(valueAccessor());
return ko.bindingHandlers.foreach.update.call(this, element, valueAccessor, allBindings, viewModel, bindingContext.extend({
'$foreachContext' : extendedContext
}));
}
};
})();
ko.virtualElements.allowedBindings.xforeach = true;
公开有关项目/数组的上下文的自定义template
绑定:
ko.bindingHandlers.xforeachItem = (function() {
var createContext = function(currentContext, forEachContext) {
return {
first: function() { return currentContext.$index() === 0; },
last: function() { return currentContext.$index() === (forEachContext.$arrayLength() - 1); }
};
};
return {
init: ko.bindingHandlers.template.init,
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var extendedContext = createContext(bindingContext, bindingContext.$parentContext.$foreachContext);
return ko.bindingHandlers.template.update.call(this, element, valueAccessor, allBindings, viewModel, bindingContext.extend({
'$foreachItemContext' : extendedContext
}));
}
};
})();
ko.virtualElements.allowedBindings.xforeachItem = true;
示例用法:
<div data-bind="xforeach: items">
<div data-bind="xforeachItem: {}">
<input type="text" data-bind="value: description" />
<span data-bind="visible: $foreachItemContext.first(), text: $foreachContext.$arrayLength()"></span>
<button data-bind="visible: $foreachItemContext.last(), click: $root.add">Add Another</button>
</div>
</div>
最后,一个小提琴展示了它的实际效果:http: //jsfiddle.net/magnafides/wkCLd/2/