【问题标题】:Knockout.js Workflow with Mapping plugin带有映射插件的 Knockout.js 工作流
【发布时间】:2014-06-03 03:21:32
【问题描述】:

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

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

每个ids 对应一个可以属于current 的值。现在,复杂性出现了,因为在填充我的 viewModel 的初始 ajax 请求中,服务器以current: null 响应。我已经编写了代码以从ids 列表中取出第一个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

我是否正在尝试做一些 Knockout 不适合做的事情?我需要另一层抽象吗?您将如何处理这种情况?

【问题讨论】:

    标签: javascript knockout.js


    【解决方案1】:

    当您调用 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" />
      
    • 如果您正在处理嵌套属性,最好和最推荐的选项可能是使用with binding

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

    演示JSFiddle.

    【讨论】:

    • 不过就是这样。在调用 applyBindings 之前,我正在调用 viewModel.head(填充当前)。
    • 是的,你在ko.applyBindings之前调用viewModel.head,但是head没有直接设置currentcurrentaync$.getJSON 回调中设置。因此设置current 最终只会在ko.applyBindings 之后发生,因此您需要使用上述技术之一来修复它。
    • 好的,我现在明白了。我没有意识到 JavaScript 中可能存在竞争条件。谢谢!
    猜你喜欢
    • 2016-01-25
    • 2013-01-07
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 2012-01-07
    • 2013-07-12
    相关资源
    最近更新 更多