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

时间:2017-01-26 15:02:23

标签: javascript knockout.js

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

JSFiddle for easy testing

我有以下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实例)中的当前项,而不是包含对象(a 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 -->

它不漂亮但它有效。它基本上归结为在foo之前为foreach属性打开新范围。

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

1 个答案:

答案 0 :(得分:2)

每次使用控制流绑定(例如'with'或'foreach')(onOptionsItemSelected(android.view.MenuItem))时,都会创建Knockout绑定上下文。所以我认为混淆是绑定层次结构是由html决定的,而不是由你的视图模型决定的。在您的视图模型中,层次结构是ViewModel - &gt; Foo - &gt;条形码,但在标记中有$ root是ViewModel,然后创建的下一个上下文是Bars对象,所以它的父对象直接映射到ViewModel,从而跳过了Foo。

至于更好的方式......我实际上并不介意使用With绑定我认为它使得代码更清晰,而不是在每个绑定上深入了解foo。在这种情况下更好的是纯粹的意见。您可以使用$ parent.foo.removeBar而不是$ root.foo.removeBar,因为您知道在您的上下文中那些引用相同的东西。第三种选择是使用Foo本身作为你的根视图模型,因为除了在这个例子中提供Foo之外它似乎没什么用,但是你的实际用例可能更复杂。