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

Javascript Knockout.js-$parent未按预期工作,javascript,knockout.js,Javascript,Knockout.js,(我知道标题不是最好的——请随意编辑) 我有以下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()); };

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

我有以下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>
项目移除停止工作;但是,我在控制台上没有看到任何错误

通过一些实验,我可以发现这里的
$parent
指的是可观察数组中的当前项(一个
实例),而不是包含对象(一个
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”之类的控制流绑定时,都会创建敲除绑定上下文()。所以我认为混淆之处在于绑定层次结构是由html决定的,而不是由视图模型决定的。在视图模型中,层次结构是ViewModel->Foo->bar,但在标记中有$root,它是ViewModel,然后创建的下一个上下文是bar对象,因此它的父对象直接映射到ViewModel,从而跳过Foo


就更好的方式而言。。。事实上,我并不介意您使用的绑定,我认为它使代码比在每个绑定上深入到foo更干净。在这种情况下,最好是纯粹的意见。您可以交替使用$parent.foo.removeBar而不是$root.foo.removeBar,因为您知道,在您的上下文中,它们指的是同一事物。第三种选择是使用Foo本身作为根视图模型,因为在本例中,它除了提供Foo之外似乎没有什么作用,但您的实际用例可能更复杂。

谢谢@JasonSpake,非常好的解释!我的实际用例确实要复杂得多,重要的是不要依赖于属性的完整路径(我使用各种帮助函数生成HTML的一部分)。
<!-- 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 -->