是否可以推迟计算的observable直到某些UI元素变得可见?

时间:2013-04-29 21:02:12

标签: javascript knockout.js

我的模型中有一个计算的observable,如下所示:

   this.TrainingPlanTemplates = ko.computed(function ()
   {
      var workgroups = model.WorkgroupsImpacted();
      var areas = model.AreasImpacted();
      var plans = model.PrescribedPlan();

      $(plans).each(function (i, v)
      {
         // A bunch of stuff that really slows everything down
      });

      // ...
   }

然后我有一个UI模板:

<table>
   <!-- ko foreach: TrainingPlanTemplates -->
   <tr> ... Various columns bound to TrainingPlanTemplates properties ... </tr>
   <!-- /ko -->
</table>

问题是,上面的HTML模板包含各种自定义绑定处理程序,并且可能包含大量数据。渲染此表有点慢(如5秒左右)。此UI使用jQuery UI tabs control,因此在页面加载时我甚至不会显示数据。大多数用户甚至都不会切换到该选项卡,这意味着我通常会浪费时间绑定数据。

问题:有没有办法推迟计算observable的绑定,直到我这样说,例如,直到某个jQuery选项卡变为活动状态?

思路:

我从this page得到了一些想法。确实存在一个 deferEvaluation 属性,但这只会将属性推迟到访问它的地方,这将立即发生,因为隐藏的HTML表仍然绑定到数据。

一个想法是创建一个名为 TrainingPlanTemplatesLoaded 的新 observable 属性,并在该选项卡变为活动状态时将其设置为 true 。然后,在 TrainingPlanTemplates TrainingPlanTemplatesLoaded 之间创建依赖关系,以便当 TrainingPlanTemplatesLoaded 更改时, TrainingPlanTemplates 实际加载到实际数据中

关于实现这一目标的最佳方法还有其他想法吗?

2 个答案:

答案 0 :(得分:3)

是的,只需制作另一个可以在计算之前检查的观察结果:

// set to true when you want the computation to run
this.TrainingPlanTemplatesLoaded = ko.observable(false);
this.TrainingPlanTemplates = ko.computed(function ()
{
  if (this.TrainingPlanTemplatesLoaded()) {
      var workgroups = model.WorkgroupsImpacted();
      var areas = model.AreasImpacted();
      var plans = model.PrescribedPlan();

      $(plans).each(function (i, v)
      {
         // A bunch of stuff that really slows everything down
      });

      // ...
  }
}, this);

答案 1 :(得分:0)

当然可能,see my example

function VM(){
    var self = this;
    self.FirstName = ko.observable("John");
    self.LastName = ko.observable("Smith");
    self.canShow = ko.observable(false);
    self.FullName = ko.computed(function(){
        if (self.canShow()){
            return self.FirstName() + " " + self.LastName();
        }
    });
}
myVm = new VM();
ko.applyBindings(myVm);

// Represents that at some point
// Some function make something happen
setTimeout(function(){
    // Let's say we check if an element was visible
    // or check anything that we want to know has happened, then:
    myVm.canShow(true);
}, 4000);


<p data-bind="text: FirstName"></p>
<p data-bind="text: LastName"></p>
<p data-bind="text: FullName"></p>