Knockout.js-$parent未按预期工作



(我知道标题不是最好的-请随意编辑)

JSFiddle便于测试

我有以下Knockout.js视图模型:

function Bar() {
var self = this;
self.baz = "baz";
}
function Foo() {
var self = this;
self.bars = ko.observableArray([]);
self.addBar = function () { self.bars.push(new Bar()); };
self.removeBar = function (bar) { self.bars.remove(bar); };
}
function ViewModel() {
var self = this;
self.foo = new Foo();
}
ko.applyBindings(new ViewModel());

以及以下HTML:

<a href="#" data-bind="click: foo.addBar">Add</a>
<ul data-bind="foreach: foo.bars">
<li><span data-bind="text: baz"></span> <a href="#" data-bind="click: $root.foo.removeBar">Remove</a></li>
</ul>

这是意料之中的事。但如果我把绝对路径$root.foo.removeBar改成$parent.removeBar,就像这样:

<a href="#" data-bind="click: $parent.removeBar">Remove</a>

项目移除停止工作;但是,我在控制台上没有看到任何错误。

通过一些实验,我可以发现$parent在这里指的是可观察数组中的当前项(Bar实例),而不是包含对象(Foo实例)。

我的问题是:如何在绑定中使用相对引用引用包含对象

编辑:我找到了一种有效的方法:

<!-- ko with: foo -->
<ul data-bind="foreach: bars">
<li>
<span data-bind="text: baz"></span>
<a href="#" data-bind="click: $parent.removeBar">Remove</a>
</li>
</ul>
<!-- /ko -->

它不漂亮,但很管用。它基本上可以归结为在foreach之前为foo属性打开一个新的作用域。

所以我的下一个问题是:有更好的方法吗

每次使用控制流绑定(如"with"或"foreach")时,都会创建Knockout绑定上下文(引用)。因此,我认为混淆的地方在于绑定层次结构是由html决定的,而不是由视图模型决定的。在视图模型中,层次结构是ViewModel->Foo->Bars,但在标记中有$root,它是ViewModel,然后创建的下一个上下文是Bars对象,因此它的父对象直接映射到ViewModel,从而跳过Foo。

还有更好的方法。。。事实上,我并不介意你有With绑定。我认为这比每次绑定都要深入到foo更干净。在这种情况下,更好的是纯粹的意见。你可以交替使用$parent.foo.moveBar而不是$root.foo.removeBar,因为你知道在你的上下文中它们指的是同一个东西。第三种选择是使用Foo本身作为根视图模型,因为在本例中,它除了提供Foo之外似乎没有做太多其他事情,但您的实际用例可能更复杂。

最新更新