在激活中获取数据时的 Durandal KO 绑定

Durandal KO binding when data is fetched in activate

一个参数控制要显示的数据。该参数是从视图模型的 activate 方法中的 activationData 检索的,并用于调用 Web Api 方法。返回数据,并像这样添加到视图模型

define(['durandal/app', 'knockout', 'moment'], 
       function (app, config, ko, moment) {

  var vm = {
    app: app
  };

  vm.activate = function (activationData) {
    vm.ChecklistInstanceId = activationData.ChecklistInstanceId;
    $.ajax({
      url: "api/ChecklistInstance/" + vm.ChecklistInstanceId,
      headers: { Authorization: "Session " + app.SessionToken() }
    }).done(function (data) {
      $.extend(vm, ko.mapping.fromJS(data));
    });    
  };

  return vm;

});

在扩展后立即检查视图模型表明它完全按照预期使用可观察对象进行了装饰。例如,vm.Caption() 存在并且 returns 我期望的字符串,并且 vm.Section() 是一个适当填充的可观察数组,依此类推一个相当复杂的对象图。

问题是绑定阶段已经发生,那时视图模型缺少我尝试绑定的所有可观察对象。

有两种可能的策略:

我不知道如何做这两件事。谁能告诉我如何重新组织我的代码以允许绑定到参数化获取的数据?

我想到了第三种可能:

define(['durandal/app', 'knockout', 'moment'], 
       function (app, config, ko, moment) {

  var vm = {
    app: app,
    Caption: ko.observable(),
    Section: ko.observableArray()
  };

  vm.activate = function (activationData) {
    vm.ChecklistInstanceId = activationData.ChecklistInstanceId;
    $.ajax({
      url: "api/ChecklistInstance/" + vm.ChecklistInstanceId,
      headers: { Authorization: "Session " + app.SessionToken() }
    }).done(function (data) {
      var foo = ko.mapping.fromJS(data);
      vm.Caption(foo.Caption());
      vm.Section(foo.Section());
    });    
  };

  return vm;

});

这是可行的,因为所有可观察对象都存在于绑定阶段。考虑到我只描述了潜在深层对象图的根,这可能看起来令人惊讶,但可观察数组为空的事实导致绑定阶段顺利退出。

稍后在激活处理程序中,值被添加到可观察数组 ko.mapping 处理数据后,绑定成功。

我对此有一种似曾相识的感觉:这令人毛骨悚然地想起八十年代在 TurboPascal 中使用前向声明解决的问题。 La plus ça 变化...

为了处理完全构建的视图,您需要将逻辑移至 attached 处理程序或 compositionComplete 处理程序。如您所说,在 activate 阶段, DOM 尚未完全构建。您可以阅读这些生命周期回调 here.

通常,我们所做的是通过 activate 处理程序传递激活数据,将激活数据存储在本地(如果您的 viewModel 是基于实例的,则在构造函数中的 属性 上),然后在 attachedcompositionComplete 处理程序中引用该 activationData。

您可以在 activate 处理程序中获取数据,然后将数据存储在本地。但这就是你应该做的。为周期的后期保留与视图相关的逻辑。在这种情况下,您可能需要 return 来自 activate 的承诺,然后在收到您的数据后解决。你可以阅读它 here.

更新

看看 this post,那里的对话。