KnockoutJS:如何避免在applyBindings上运行viewmodel函数?

时间:2013-12-09 06:00:00

标签: javascript knockout.js

我对有些代码感到有些困惑,我把它放在一起并没有像我期望的那样表现。

我确定我做错了(并且考虑到这里的时间很晚,这可能是一件简单的事情),但我正在寻找一些明确的原因。

我正在使用:

  • jQuery 1.10.2
  • Knockout 2.3.0
  • Bootstrap 3.0.3

问题

  • 我在ViewModel中定义了一个函数,它将一个observable设置为某个值。
    • 我的代码中的任何其他地方都没有调用它。
  • 我在一个按钮组的按钮上定义data-bind="click: AddAnnouncement"绑定。
  • 调用ko.applyBindings(vm)时,AddAnnouncement函数会触发,在我点击任何内容之前很久就会给我一个不受欢迎的结果。

问题代码

可以在JSFiddle中找到:http://jsfiddle.net/SeanKilleen/v8ReS/

基本上,我有以下JavaScript代码:

var MyNamespace = MyNamespace || {

    ViewModel: function(){
        'use strict';
        var self = this;

        self.AddingAnnouncement = ko.observable(false);

        self.AddAnnouncement = function(){
            self.AddingAnnouncement(true); 
        };

        self.Start = function(){
            self.AddingAnnouncement(false);
        };

        self.Start();
    }
};

var vm;

$(document).ready(function(){
'use strict';

vm = new MyNamespace.ViewModel();

 ko.applyBindings(vm); 
    //do something with jQuery? Bind a VM?
});

我的绑定代码也非常简单(我想):

<div class="container">
    <div class="row">
        <div class="btn-group">
            <button type="button" class="btn btn-default"><abbr Title="Announcement" data-bind="click: AddAnnouncement()">A</abbr>

            </button>
        </div>
    </div>
    <div class="row" data-bind="visible: AddingAnnouncement() == true">
            <h1>Add a new announcement</h1>

    </div>
</div>

认为正在做什么

我认为有问题的代码正在执行以下操作:

  • 定义名为MyNamespace的命名空间(尽管可能不是最好的方式;这可能是问题的一部分?)
  • 在命名空间内定义ViewModel对象
  • ViewModel对象提供一个名为AddingAnnouncment的可观察对象和一个名为AddAnnouncement的函数,该对象将AddingAnnouncement设置为true。
  • 定义Start方法,确保默认情况下AddingAnnouncement设置为false;
  • 调用Start方法作为初始化的最后一步。

我在这里缺少什么?

我认为我没有理解JavaScript的某些标准行为或类似于敲除绑定模型的方式,但似乎在应用绑定时,knockout执行所有函数,即使对于单击绑定也是如此。但是,这对我来说没有意义,所以我打赌我错了。

有人开导我吗?谢谢!

2 个答案:

答案 0 :(得分:6)

Whooops!这个问题的答案结果证明是在我的鼻子底下;事实上,我所要做的就是在看到它之前写下那个完整的问题。 :)

问题在于我的绑定:

<button type="button" class="btn btn-default"><abbr Title="Announcement" data-bind="click: AddAnnouncement()">A</abbr>

请注意一个非常重要的区别:AddAnnouncement()。在这种情况下,()非常重要。

当knockout分配其绑定时,它会通过直接引用您输入的内容来实现。自从我输入AddAnnouncement()以来,它将绑定分配给已运行一次的函数的输出,而不是将在稍后执行的函数本身。

最好的方法就是使用AddAnnouncment,而不使用paranetheses,就像这样:

<button type="button" class="btn btn-default"><abbr Title="Announcement" data-bind="click: AddAnnouncement">A</abbr>

这不会在应用绑定时执行该功能。

虽然我忘了避免这么简单的错误,但我希望将来能节省别人的时间。工作的JSFiddle可以在http://jsfiddle.net/SeanKilleen/v8ReS/4/找到。

答案 1 :(得分:1)

当我们将查看 ViewModel 绑定时,我们通常会混淆何时使用括号()

当你绑定AddAnnouncement函数时,你直接绑定函数调用,如AddAnnouncement()。使用AddAnnouncement进行绑定时ko.applyBindings函数调用的原因即使我们没有单击按钮,函数调用也已触发。

<div class="row">
    <div class="btn-group">
        <button type="button" class="btn btn-default">
            <abbr Title="Announcement" data-bind="click: AddAnnouncement()">
               A
            </abbr>
        </button>
    </div>
</div>

所以我们改变如下

<div class="row">
    <div class="btn-group">
        <button type="button" class="btn btn-default">
            <abbr Title="Announcement" data-bind="click: AddAnnouncement">
               A
            </abbr>
        </button>
    </div>
</div>

working jsfiddle