【问题标题】:Durandal KO binding when data is fetched in activate在激活中获取数据时的 Durandal KO 绑定
【发布时间】:2015-03-02 12:06:27
【问题描述】:

参数控制要显示的数据。该参数从视图模型的 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() 存在并返回我期望的字符串,而 vm.Section() 是一个适当填充的可观察数组,依此类推,形成一个相当精细的对象图。

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

建议有两种可能的策略:

  • 提前获取参数
  • 重新绑定

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

【问题讨论】:

    标签: durandal knockout-mapping-plugin


    【解决方案1】:

    我想到了第三种可能性:

    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 change...

    【讨论】:

      【解决方案2】:

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

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

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

      更新

      看看this post,以及那里的对话。

      【讨论】:

      • 我关注了你的链接。我是否正确理解您试图告诉我的本质是让激活需要一段时间才能返回是一个坏主意?我原以为我提出的解决方案中 ajax 调用的 done 方法已经设置为异步填充数据。有什么我错过的吗?
      • 没关系,我现在看到,如果我在 activate 中捕获参数,然后使用它来获取附加的数据,我可以简化回 $.extend(vm, ko.mapping.fromJS(data)); 我不知道如何重写我的 ajax 调用所以它给了我一个返回的承诺对象,但我相信我可以解决这个问题。
      • @PeterWone 不,我并不是说这是个坏主意。事实上,由于您是异步获取数据,因此必须有一点延迟。同样,可能没有必要返回。我没有,我也在 activate 处理程序中异步获取数据。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      • 2015-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多