Javascript 带有映射插件的Knockout.js工作流

Javascript 带有映射插件的Knockout.js工作流,javascript,knockout.js,Javascript,Knockout.js,我不确定我是否理解工作流Knockout.js在内部遵循的内容。我有一个使用映射插件动态定义的ViewModel。它的形状是: { current: { foo: 'foo', bar: 'bar', id: 0 } , ids: [1,2,3,4,5] } 这些id中的每一个都对应于可以属于当前的值。现在,问题变得复杂了,因为在填充我的viewModel的初始ajax请求中,服务器响应为current:null。我编写了代码,从id列表中取出第一个id,并运行另一个ajax查询来填

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

{ current: { foo: 'foo', bar: 'bar', id: 0 }
, ids:     [1,2,3,4,5] 
}
这些
id
中的每一个都对应于可以属于当前
的值。现在,问题变得复杂了,因为在填充我的viewModel的初始ajax请求中,服务器响应为
current:null
。我编写了代码,从
id
列表中取出第一个
id
,并运行另一个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()
对象,我就在完整的
viewModel
上调用
ko.applyBindings
。我可以确认,当一切尘埃落定时,
viewModel.current
不是
null
。但我仍然得到了错误:

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

我是不是想做一些击倒比赛不是设计来做的?我需要另一层抽象吗?如何处理这种情况?

当您调用
ko.applyBindings
时,首先对绑定进行评估

因此,如果此时您的
当前
属性包含
null
,则您得到的
无法读取null
异常的属性“foo”是正常的

此问题有多种解决方案:

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

  • 您可以在绑定中添加一个额外的条件,以检查
    current
    是否具有某些值:

    <input type="text" data-bind="value: current() && current().foo" />
    

演示。

不过,这就是问题所在。在调用applyBindings之前,我调用了viewModel.head(它填充当前值)。是的,您在
ko.applyBindings
之前调用了
viewModel.head
,但是
head
不会直接设置当前值。当前
在一个名为aync的
$.getJSON
回调中设置。因此,只有在
ko.applyBindings
之后,才能最终将
设置为当前值。因此,您需要使用上述技术之一来修复它。好的,我现在明白了。我没有意识到在JavaScript中种族条件是可能的。非常感谢。
<input type="text" data-bind="value: current() && current().foo" />
<!-- ko with: current -->
    <input type="text" data-bind="value: foo" />
<!-- /ko -->