在foreach中敲除自定义绑定以获取迭代器

时间:2015-02-14 16:22:15

标签: javascript knockout.js

我正在尝试制作一个在foreach绑定中使用的自定义绑定,并且需要访问当前的observableArray$data

现在我注意到bindingContext arg包含$data, $parent, $root等但是我似乎无法找到一种方法来访问正在迭代的数组,所以有办法吗?

这里要清楚的是我的意思的一个例子:

<div data-bind="foreach: People">
   <button data-bind="customBinding: someArg">DoSomethingWithArrayAndElement</button>
</div>

在这种情况下,customBinding似乎会产生:

  • $ data =迭代中的当前元素
  • $ parent =包含People数组
  • 的视图模型
  • root =与$ parent相同
  • $ index =迭代数组中的当前索引
  • $ parents =包含视图模型的数组

2 个答案:

答案 0 :(得分:2)

我不确定这是否可行,但如果没有进一步了解您的应用程序,我唯一可以建议的是:制作一个自定义foreach绑定,以暴露整个数组。

ko.bindingHandlers.customForeach = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
      var newBindingContext = bindingContext.extend({iterator: valueAccessor()});

      return ko.bindingHandlers.foreach.init(element, valueAccessor, allBindingsAccessor, viewModel, newBindingContext);
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
      var newBindingContext = bindingContext.extend({iterator: valueAccessor()});

      return ko.bindingHandlers.foreach.update(element, valueAccessor, allBindingsAccessor, viewModel, newBindingContext);
    }
  };

var ViewModel = function ViewModel() {
  this.items = ko.observableArray(['a', 'b', 'c', 'd']);
  };

ko.applyBindings( new ViewModel() );
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<ul data-bind="customForeach: items">
  <li data-bind="text: $data"></li>
</ul>

这会为您的bindingContext添加一个新的iterator属性,从而在其中公开完整的数组。

答案 1 :(得分:2)

那么您的目标是在foreach模板中访问基础数组?如果您问我,那么不应该以这种方式为您的代码建模。

话虽如此,您真正需要的只是数组的别名,并确保在使用foreach绑定时设置别名。当然,有很多方法可以做到这一点。

最简洁的方法可能是创建一个alias绑定处理程序。然后扩展现有的foreach绑定以添加别名或创建一个新别名。

ko.bindingHandlers.alias = {
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var value = valueAccessor();
        var aliasValue = value.data;
            aliasName = value.aliasName || '$alias';
        if (ko.isObservable(aliasValue)) {
            var rawValue = aliasValue,
                rawAliasName = value.rawAliasName || '$rawAlias';
            bindingContext[rawAliasName] = rawValue;
            aliasValue = rawValue();
        }
        bindingContext[aliasName] = aliasValue;
    }
};
ko.bindingHandlers.foreachex = {
    preprocess: function (value, name, addBinding) {
        addBinding('alias', "{ data: "+value+", aliasName: '$source', rawAliasName: '$rawSource' }");
        addBinding('foreach', value);
    }
};

然后您可以在视图中使用别名。

<div data-bind="foreachex: People">
    <!-- $rawSource is the People observable array -->
    <button data-bind="customBinding: someFunction($rawSource, $data)">
        DoSomethingWithArrayAndElement
    </button>
</div>

fiddle