observable未定义在object literal knockout中

时间:2012-12-21 14:54:59

标签: knockout.js knockout-2.0

我在一个淘汰视图模型的对象文字中定义了一个observable。现在当我运行应用程序时。它无法访问observable。

$(function () {
  var viewModel =    {
    Folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
    Title: ko.observable("My View Model Test"),
    SelectedFolder: ko.observable(),
    Mails: ko.observableArray(),
    SelectedMail: ko.observable(),
    SelectedChoices: ko.observable(false),


    navigate: function (folder) {           
        SelectedFolder(folder);
        $.ajax({
            url: "/Api/MailBox",
            data: { folder: folder },
            success: function (data) {
                self.Mails(data);
            },
            statusCode: {
                404: function () {
                    console.log("No Mails");
                }
            }

        });
    }
};
}

当我将click事件绑定到navigate函数时。它说SelectedFolder未定义。有人能告诉我为什么它无法访问SelectedFolder函数中的navigate可观察对象?

2 个答案:

答案 0 :(得分:2)

当导航方法正在运行并且它查找SelectedFolder observable时,它首先在导航方法的上下文中查找它。如果失败了,它会跳转到父上下文,这是在页面准备好时运行的匿名函数。如果失败了,它会跳转到全局上下文 - 它在那里找不到SelectedFolder,所以它就放弃了。

要解决此问题,请更改导航方法以引用在页面准备就绪时正在运行的匿名函数的上下文中可用的viewModel变量:

navigate: function (folder) {           
  viewModel.SelectedFolder(folder);
  $.ajax({
    url: "/Api/MailBox",
    data: { folder: folder },
    success: function (data) {
      viewModel.Mails(data);
    },
    ...

请注意,我还在成功回调中添加了对viewModel的引用,以便它可以找到Mails observable。

这应该可行,但是,我建议考虑更改您的结构,以便您的导航方法不依赖于特定的全局变量。这是一种方式:

var myViewModel = function() {
    var self = this;
    self.Folders = ['Inbox', 'Archive', 'Sent', 'Spam'];
    self.Title = ko.observable("My View Model Test");
    self.SelectedFolder = ko.observable();
    self.Mails = ko.observableArray();
    self.SelectedMail = ko.observable();
    self.SelectedChoices = ko.observable(false);

    self.navigate = function (folder) {           
        self.SelectedFolder(folder);
        $.ajax({
            url: "/Api/MailBox",
            data: { folder: folder },
            success: function (data) {
                self.Mails(data);
            },
            statusCode: {
                404: function () {
                    console.log("No Mails");
                }
            }

        });
    };
};

$(function () {
  var ViewModel = new myViewModel();
  ko.applyBindings(viewModel);
});

答案 1 :(得分:1)

问题可能是调用该方法时的当前上下文。如果click方法正在调用该方法,则this可能是click事件绑定的对象,因此它会尝试在该元素上找到SelectedFolder方法。

不确定这是否是最好的方法,但这是一个可能的解决方案:

var viewModel =    {
  Folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
  Title: ko.observable("My View Model Test"),
  SelectedFolder: ko.observable(),
  Mails: ko.observableArray(),
  SelectedMail: ko.observable(),
  SelectedChoices: ko.observable(false)
};

viewModel.navigate = function (folder) {           
  viewModel.SelectedFolder(folder);
  $.ajax({
    url: "/Api/MailBox",
    data: { folder: folder },
    success: function (data) {
      viewModel.Mails(data);
    },
    statusCode: {
      404: function () {
        console.log("No Mails");
      }
    }
});