(我知道标题不是最好的-请随意编辑)
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之外似乎没有做太多其他事情,但您的实际用例可能更复杂。