【问题标题】:Knockout binding is undefined for click敲除绑定未定义单击
【发布时间】:2012-12-06 09:40:25
【问题描述】:

我有一个视图模型,它必须附加到<li> 标记的点击事件。这是视图模型和标记

  var viewModel =
    {
        Folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
        SelectedFolder: ko.observable('Inbox'),
        chosenFolderId: ko.observable(),
        navigate: function () {
            self.chosenFolderId(folder);               
        }
    };
ko.applyBindings(viewModel);

标记是

   <ul class="nav nav-list bs-docs-sidenav affix" data-bind="foreach:Folders">
                @*<li data-bind="css:{active: $data == chosenFolderId() }">*@
                <li>
                    <a href="#" data-bind="click:navigate">                      
                        <!-- ko text: $data -->
                        <!-- /ko -->
                        <i class="icon-chevron-right"></i>
                    </a>
                </li>                   
            </ul>

问题出在这一行

<a href="#" data-bind="click:navigate"> 

<li data-bind="css:{active: $data == chosenFolderId() }">

上面的行没有分别附加到Navigate 函数和chosenFolderId observable。它说 Navigate 是 undefined 。无法解析. Same goes forchosenFolderId`。

知道为什么会这样吗?

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    您当前的方法存在一些问题:

    当您在ul 中使用foreach binding 例如data-bind="foreach:Folders" 时,“当前上下文”将是您文件夹集合中的项目。

    因此,如果您想访问navigatechosenFolderId 方法,您需要使用$parent$root 来访问您的“根”视图模型(您可以阅读有关binding context 的更多信息) :

    <ul class="nav nav-list bs-docs-sidenav affix" data-bind="foreach:Folders">
        <li data-bind="css:{active: $data == $parent.chosenFolderId() }">
            <a href="#" data-bind="click: $parent.navigate">                      
                <!-- ko text: $data -->
                <!-- /ko -->
                <i class="icon-chevron-right"></i>
            </a>
        </li>                   
    </ul>​
    

    你的视图模型也有问题。如果你有像navigate 这样尝试使用self 的复杂函数,你应该使用函数作为视图模型而不是可以存储this 的对象文字:

    var viewModel = function() {
        var self = this;
        self.Folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
        self.SelectedFolder = ko.observable('Inbox');
        self.chosenFolderId = ko.observable();
        self.navigate = function(folder) {
            self.chosenFolderId(folder);
        }
    };
    ko.applyBindings(new viewModel());​
    

    请注意:您的 navigate 函数需要一个 folder 参数才能使其工作,并且 Knockout 将为您传递当前项目。

    这是working JSFiddle

    如果您想使用对象字面量作为您的视图模型,这里是 JSFiddle,它演示了这种方法。

    但是,您应该知道两种视图模型创建方法的优势和劣势。这个 SO 问题总结得很好:Difference between knockout View Models declared as object literals vs functions

    【讨论】:

    • 是的,我已经用这种寻求的方法做到了。但我希望它与模块化模式有关,而不是仅仅通过函数推送绑定。所以用你的方法完全有效。我不能用我的方法做同样的事情吗?
    • @Joy 我并没有真正关注您...您可以使用模块化模式组织您的视图模型创建功能。你能用你想象的代码更新我的jsfiddle吗?
    • @Joy 有几种方法可以使它与像这样的对象文字一起工作:jsfiddle.net/8Y5cv/1。但您最终会遇到一些无法满足您需求的情况。
    • 是的,你提供的最后一个小提琴。我其实是想这样放的。好吧,到目前为止,我在淘汰赛方面还是个新手。你能说出为什么对象字面量总是不适合我的需要吗?或者有一篇关于这个的好博客文章?对不起,如果我问这个太天真了
    • @Joy 关于它有一个很好的 SO 问题:stackoverflow.com/questions/9589419/…。此外,关于 KO 的 plurasight 课程非常好,尽管它们不是免费的。
    猜你喜欢
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多