1

目前,当使用 Knockoutforeach绑定时,您可以使用$index. 我想为我的内部绑定提供其他类似的功能——例如:

  • array(让我访问正在操作的数组)
  • length(所述数组的长度)
  • first(当前项是否为第一项)
  • last(当前项是否为最后一项)
  • only(当前项是否为唯一项)

你明白了。不幸的是,设置的代码$index深埋在template绑定代码中,没有明显的方法来增加上下文。

我能够访问arraylength通过foreach扩展的自定义绑定bindingContext(我知道这个 re 有一些警告:destroy但它对我有用),但我不知道如何实现需要访问的其他方法没有为每个数组迭代执行的自定义内部绑定的“当前”项。

我希望能够做这样的事情:

<div data-bind="foreach: items">
  <input type="text" data-bind="value: description" />
  <button data-bind="visible: $last, click: $array.push({})">Add Another</button>      
</div>

(我们知道,既不$array也不$last存在)。假设button元素可能来自外部模板,而无法知道如何路径到当前数组(所以$parent.items.push对我不起作用)。

有没有办法做到这一点?

4

2 回答 2

1

我能想到的最好的方法是创建专门的绑定来存储有关数组和当前项目的上下文信息。

公开有关数组的上下文的自定义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/

于 2013-12-06T15:44:36.953 回答
0

您可以使用 $parent.data() 来获取实际的数组。

对于$length,您可以这样做:

$parent.items.length

对于$first,您可以这样做:

$index() == 0

对于$last,您可以这样做:

$index() == ($parent.items.length - 1)

对于$only,您可以这样做:

$index() == 0 && $parent.items.length == 1

这是小提琴

于 2013-11-14T17:11:18.890 回答