Javascript 淘汰赛';单击';绑定不起作用

Javascript 淘汰赛';单击';绑定不起作用,javascript,knockout.js,Javascript,Knockout.js,我正在尝试将单击事件绑定到列表项。当我单击下面的列表项时,它应该在javascript中启动updateCurrent函数,但它什么都不做 注意:我在调用函数时使用了$parent.updateCurrent,因为我在currentCat上下文中,而updateCurrent函数在ViewModel上下文中 HTML: 当我单击列表名时,我没有得到任何错误,但console不会记录任何内容 我相信我没有正确地使用上下文,但我无法理解这里的确切问题。任何帮助都将不胜感激 您处于两个级别的上下文中。

我正在尝试将单击事件绑定到列表项。当我单击下面的列表项时,它应该在javascript中启动
updateCurrent
函数,但它什么都不做

注意:我在调用函数时使用了
$parent.updateCurrent
,因为我在
currentCat
上下文中,而
updateCurrent
函数在
ViewModel
上下文中

HTML:

当我单击列表名时,我没有得到任何错误,但console不会记录任何内容


我相信我没有正确地使用上下文,但我无法理解这里的确切问题。任何帮助都将不胜感激

您处于两个级别的上下文中。带有绑定的
表示
div
中的
$data
currentCat
foreach
提供了另一个层次的上下文
$parent
不是指对象的父对象,而是指此上下文之外的上下文。你可以用


当你说
$parent.catNames
时,你只在
中有
上下文,因此它在
ViewModel
中引用
catNames
,因为没有其他封闭上下文。但是如果你说
$parent.updateCurrent
,你就从
foreach
上下文跳到了
with
上下文。您想再跳一个。

当您说$parent.catNames时,您指的是ViewModel,因为它是层次结构中直接父对象的一个自有属性。使用foreach绑定,您将处于一个新的上下文中;因此,在$parent.updateCurrent中,层次结构中的直接父级将成为catNames数组中的项

正如Viktor所提到的,在这种情况下,您可以使用$root,但实现此功能的最安全和正确的方法是一次爬升一级层次结构以获得$parents[1]

$parent等于CATNAME之一的$parents[0]$父项[1]将引用ViewModel

为什么不使用$root?

敲除将使您的DOM和绑定上下文保持比显而易见的更深的层次。在模板绑定中,$root上下文可能引用甚至不在HTML模板中的对象

<div data-bind="template: { name: 'sample', data: catNames }"></div>
<script type='text/html' id='sample'>
    <!-- ko foreach: $data -->
    <span data-bind="text: 'Cat ' + $index + ' of ' + $parents[0].length"></span>
    Returns "Cat 1 of 10"
    <!-- /ko -->

    <!-- ko foreach: $data -->
    <span data-bind="text: 'Cat ' + $index + ' of ' + $root.length"></span>
    Return "Cat 1 of undefined" because ViewModel has no length property!
    <!-- /ko -->
</script>

返回“第1类,共10类”
返回“未定义的类别1”,因为ViewModel没有长度属性!

绑定上下文文档:

尝试使用$root而不是$parents,这样做很神奇!非常感谢@ViktorKukurbaHmm,有意思的问题@ViktorKukurba的评论是一个快速解决方案,但我很惊讶KO不能像OP(和我)预期的那样解决
$parent
。是的,我也在想同样的问题,(为什么parent不起作用)。我最近开始学习敲除,所以没有足够的上下文。哦,所以当我说
parent.catNames
,parent不是指ViewModel吗?那么它指向哪里呢,currentCat的上下文?但这就是ViewModel,不是吗?+1
$root
已经腐烂了,IMO不应该被包括在内(或者至少带有肥胖健康警告)。使用root有效地意味着创建对某种形式的全局作用域的依赖(通常是因为开发人员没有学习敲除作用域是如何工作的)。随着项目的发展,使用
$root
作为范围内所有需要的垃圾场的诱惑可能变得非常有害。
var viewModel = function() {

    var self = this;
    this.catNames = ko.observableArray([]);
    this.catList = ko.observableArray([]);

    //cats is defined as a simple array of objects, having name
    cats.forEach(function(catObject) {
        self.catList.push(new cat(catObject));
        self.catNames.push(catObject.name);
    });

    //initially, set the currentCat to first cat
    this.currentCat = ko.observable(this.catList()[0]);

    //should run when the user click on the cat name in the list
    this.updateCurrent = function() {
        console.log("hello");
    }

};
<div data-bind="template: { name: 'sample', data: catNames }"></div>
<script type='text/html' id='sample'>
    <!-- ko foreach: $data -->
    <span data-bind="text: 'Cat ' + $index + ' of ' + $parents[0].length"></span>
    Returns "Cat 1 of 10"
    <!-- /ko -->

    <!-- ko foreach: $data -->
    <span data-bind="text: 'Cat ' + $index + ' of ' + $root.length"></span>
    Return "Cat 1 of undefined" because ViewModel has no length property!
    <!-- /ko -->
</script>