Javascript 去掉foreach中的自定义绑定以获得迭代器

Javascript 去掉foreach中的自定义绑定以获得迭代器,javascript,knockout.js,Javascript,Knockout.js,我正在尝试创建一个自定义绑定,该绑定将在foreach绑定中使用,并且需要访问当前的observableArray和$data 现在我注意到,bindingContextarg包含$data、$parent、$root等等,但是我似乎找不到访问正在迭代的数组的方法,所以有方法吗 这里有一个例子可以说明我的意思: <div data-bind="foreach: People"> <button data-bind="customBinding: someArg">D

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

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

这里有一个例子可以说明我的意思:

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

具有阵列和删除的dosomething
在这种情况下,
customBinding
似乎会产生:

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

我不确定这是否是一条路,但在没有进一步了解您的应用程序的情况下,这是我唯一可以建议的:为每个绑定一个自定义的绑定,公开完整的数组

ko.bindingHandlers.customForeach={
init:function(元素、valueAccessor、allBindingsAccessor、viewModel、bindingContext){
var newBindingContext=bindingContext.extend({iterator:valueAccessor()});
返回ko.bindingHandlers.foreach.init(元素、valueAccessor、AllBindingAccessor、viewModel、newBindingContext);
},
更新:函数(元素、valueAccessor、allBindingsAccessor、viewModel、bindingContext){
var newBindingContext=bindingContext.extend({iterator:valueAccessor()});
返回ko.bindingHandlers.foreach.update(元素、valueAccessor、AllBindingAccessor、viewModel、newBindingContext);
}
};
var ViewModel=函数ViewModel(){
this.items=ko.observearray(['a','b','c','d']);
};
应用绑定(新的ViewModel())


那么您的目标是在
foreach
模板中访问底层数组?如果你问我,你不应该用那种方式对你的代码建模

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

最干净的方法可能是创建一个
别名
绑定处理程序。然后扩展现有的
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>

具有阵列和删除的dosomething

你可能不得不从另一个角度来解决这个问题。您的自定义绑定应该做什么来满足它对数组的需求?我在各种视图模型中有许多重复的代码,这些代码使用一些其他常见的逻辑进行添加/删除,因此我正在考虑通过将常见的东西移动到自定义绑定(因为每个实例中的逻辑都是相同的)来提高一些重用性。因此,我只是想减少要维护的代码。如果您希望访问当前正在迭代的数组,您不能只在custombindings中使用
viewModel.people()
。viewModel提供您所需的内容。cheersViewmodel在自定义绑定中被弃用,而且它实际上不再可重复使用,因为您必须为每个类型创建一个绑定,或者确保它们都具有相同的变量名。这是考虑周到的。你确定
viewModel
被折旧了吗?我在doc的?感谢Hanks提供的示例,我将考虑是否真的值得我在中添加这种方法,以节省几行重复,尽管目前重复了大约20次。在大多数情况下,关键逻辑只需从活动阵列中移除当前元素并(通过事件系统)触发事件即可。因此,如果我们只是将其视为一种从数组中删除条目的快捷方式,而不必使用任何viewmodel函数,那么这就是这些快捷方式绑定的关键所在。这就是我的意思-它感觉像是一个乱七八糟的东西,可能还有更好的方法。可能会提出一个新问题,重点是“如何删除此代码的重复数据消除”?我强烈区分“viewmodels”(包含可通过UI执行的功能的对象)和数据模型。在我的应用程序中,
foreach
中的“删除此数组项”通常只是
单击:$parent.removietem.bind($parent,$data)
$parent
是具有
函数removietem(item){this.items.remove(item);}
的视图模型,可以是通过实例的某种继承或扩展,或者只是像当前一样直接放在那里,或者将其放在自定义绑定中。在我看来,它不是真正的业务逻辑,只是一个简单的可重复操作,它更可重用,更容易作为自定义绑定进行管理,因为它不需要遍历所有源代码,很像您将如何使用AOP风格的技术将横切关注点移出业务逻辑代码。我明白您的意思。关于Knockout,我的几个问题之一是,我发现绑定很难正确管理,在名称空间、组合等方面。对于视图和数据模型,另一方面,多年来我开发了一个相当不错的结构。这就是为什么我在可能的情况下倾向于使用它们而不是绑定。事实证明,已经有一个开放的请求,要求将一些类似的功能添加到knockout中:以允许使用前面提到的用例。但是,您已经可以访问foreach范围内的
$index
,因此我不明白为什么访问迭代器是件坏事,它只允许上下文快捷方式绑定。