使用Mapping插件的Knockout.js工作流程

时间:2014-06-02 18:00:53

标签: javascript knockout.js

我不确定我是否了解Knockout.js内部的工作流程。我有一个使用映射插件动态定义的ViewModel。它的形状是:

{ current: { foo: 'foo', bar: 'bar', id: 0 }
, ids:     [1,2,3,4,5] 
}

其中每个ids都对应一个属于current的值。现在,复杂性出现了,因为在填充我的viewModel的初始ajax请求中,服务器以current: null响应。我编写代码从id列表中取出第一个ids并运行另一个ajax查询来填充current。看起来像这样:

var ViewModel = function (data) {
  var self = this;
  ko.mapping.fromJS(data, {}, self);

  self.head = function () {
    if (self.promptIds().length != 0) {
      var nextId = _.head(self.promptIds());
      self.promptIds(_.tail(self.promptIds()));
      $.getJSON("my-url" + "/" + nextId, function (data) {
        self.current(ko.mapping.fromJS(data));
      });
    }
  }
}


$('document').ready ( function () {
  $.getJSON("view-model-route", function (data) {
    viewModel = new ViewModel(data);
    viewModel.head();
    ko.applyBindings(viewModel);
  });
});

请注意,在第二个块中,我创建了一个新的ViewModel对象,并在其上调用head()。填充viewModel.current()对象后,我会在完整的ko.applyBindings上致电viewModel。我可以确认,当尘埃落定后,viewModel.current不是null。但我仍然得到错误:

Uncaught TypeError: Unable to parse bindings.
  Bindings value: text: current().foo
  Message: Cannot read property 'foo' of null

我是否正在尝试做Knockout没有设计的事情?我需要另一层抽象吗?你会如何处理这种情况?

1 个答案:

答案 0 :(得分:2)

当您致电ko.applyBindings时,首先评估绑定。

因此,如果您的current属性在此时间内包含null,那么您获得Cannot read property 'foo' of null例外是正常的。

这个问题有多种解决方案:

  • 使用空对象初始化current,以便正确解析current().foo(但其值为undefined):

    viewModel = new ViewModel(data);
    viewModel.head();
    viewModel.current({});
    ko.applyBindings(viewModel);
    
  • 您可以在绑定中添加额外条件,以检查current是否有某些值:

    <input type="text" data-bind="value: current() && current().foo" />
    
  • 如果你正在处理嵌套的proeprties,那么最好也是最推荐的选择是使用with binding

    <!-- ko with: current -->
        <input type="text" data-bind="value: foo" />
    <!-- /ko -->
    

演示JSFiddle