为什么这两个函数的上下文不同

时间:2015-05-05 17:52:58

标签: javascript knockout.js

我有以下代码:

function ViewModel() {
    var self = this;

    self.newCategory = {
        name: ko.observable(''),
        canSubmit: function() {
            return this.name() !== '';
        },
        submit: function() {
            var data = 'name=' + this.name();
            $.post('/api/createcategory', data, function(res) {
                //...
            });
        }
    };
}

和HTML

<button type="button" data-bind="enable: newCategory.canSubmit(), click: newCategory.submit">Create category</button>

canSubmit()函数中,this指的是self.newCategory,正如我所期待的那样。但是,由于submit()函数的某些原因,this引用ViewModel()为什么会这样?

1 个答案:

答案 0 :(得分:3)

Knockout在它们绑定的viewmodel的上下文中调用函数,在您的情况下是主视图模型。提示:submit的视图模型不是您分配给newCategory的对象。

在你的装订中,你会做两件事:

  • enable: newCategory.canSubmit()newCateory上立即调用该函数。这就是this将在函数内部的内容。
  • click: newCategory.submit 提及该函数,即knockout创建一个将在当前视图模型的上下文中运行的点击处理程序。

请注意,canSubmit实际上应该是可观察的。

当您更改绑定上下文时,例如使用with绑定,行为就像您期望的那样。

<!-- ko with: newCategory -->
<button data-bind="enable: canSubmit, click: submit">Create category</button>
<!-- /ko -->

对于子视图模型,我喜欢创建实际的独立构造函数:

function Category() {
    var self = this;

    self.busy = ko.observable(false);
    self.name = ko.observable('');
    self.canSubmit = ko.computed(function() {
        return !self.busy() && self.name() > '';
    });
}
Category.prototype.submit = function() {
    var self = this;

    if ( !self.canSubmit() ) return;

    self.busy(true);
    $.post('/api/createcategory', {
        name: this.name()
    }).done(function(res) {
        //...
    }).always(function() {
        self.busy(false);
    });
};

function ViewModel() {
    var self = this;

    self.newCategory = new Category();
}

<!-- ko with: newCategory -->
<input type="text" data-bind="name">
<button data-bind="enable: canSubmit, click: submit">Create category</button>
<img src="spinner.gif" data-bind="visible: busy">
<!-- /ko -->