EmberJS动态观察员在运行时?

时间:2014-11-07 18:03:23

标签: javascript ember.js ember-data

鉴于以下模型:

(注意:这些是为了说明目的而简化)

App.CustomerOrder = DS.Model.extend({
  deliveries: DS.hasMany('delivery'),
  total: DS.attr('number')
});

App.Delivery = DS.Model.extend({
  orderlines: DS.hasMany('orderline')
});

App.OrderLine = DS.Model.extend({
  productid: DS.attr('string'),
  qtyordered: DS.attr('number')
});

当应用程序首次加载时,我正在查询一个API,该API向我发送有关哪些依赖项应触发更新的信息。例如,它会发给我一些类似的东西:

CustomerOrder: ["deliveries", "deliveries.orderlines", "deliveries.orderlines.qtyordered"...]

..意味着,如果从客户添加/删除交货,或者从附加到客户订单的交货中添加/删除行,或者如果订单上的qtyordered附在客户订单上的交货中,那么API期望我将序列化CustomerOrder(以及整个关系链)并发送到一个'更新'服务(即服务器/客户/更新类型的东西),它将运行各种例程和填充数据并发送整个物体链回来了。

为了便于说明,我在这里放了一个简单的例子(我知道这很容易在客户端计算,但是还有很多其他的东西会从服务器复制代码)。因此,如果订单行上的qtyordered发生变化,我需要将customerorder实例发送到服务器,在那里它将更新我的总字段。

其中一个挑战是我不能通过使用.observes()类型的东西设置观察者函数来硬编码该依赖性列表,它必须在加载依赖性数据之后动态完成(可能使用addObserver)。另一个是观察者不会像这样深入挖掘多层。

我尝试使用混合来覆盖init函数的模型,并且正是这样做。

clientchangeset: DS.attr('raw'),

init: function() {
  this._super.apply(this, arguments);
  var className = this.auth.camelizedModelString(this.constructor.toString());
  var watchlist = this.auth.dependencies[className] || null;

  var self = this;
  watchlist.forEach(function(watch) {
    if(watch.hasOwnProperty('attributeName') && watch.hasOwnProperty('collectionFlag')) {
      // {attributeName: attributeName, collectionFlag: collectionFlag}
      if(watch['collectionFlag']) {
        console.log(className+'.addObserver('+watch['attributeName']+'.@each.clientchangeset)');
        self.addObserver(watch['attributeName']+'.@each.clientchangeset', null, 'updateChangelist');
      } else {
        console.log(className+'.addObserver('+watch['attributeName']+')');
        self.addObserver(watch['attributeName'], null, 'updateChangelist');
      }  
    }
  });
},

这似乎有效,但只有一层深。为了完整性,继承了updateChangelist函数:

updateChangelist: function(src, field, value) { //jshint ignore:line

  if(this.get('pauseUpdates')) {
    return;
  }
  var className = this.auth.camelizedModelString(this.constructor.toString());

  var oldclientchangeset = this.get('clientchangeset') || [];
  console.log('Before: '+className+'.[clientchangeset]= '+oldclientchangeset);
  oldclientchangeset.pushObject(field);
  this.set('clientchangeset', oldclientchangeset);
  console.log('After: '+className+'.[clientchangeset]= '+oldclientchangeset);
}

1 个答案:

答案 0 :(得分:0)

所以一般来说,我的工作方式是按照指示创建观察者,但处理程序只是更新一个名为' _needsUpdate'在触发每个级别的关系时。 ' _needsUpdate'只是一个约会,所以当我触发时:

this.set('_needsUpdate', +new Date());

然后,当在每个级别为该级别的孩子设置观察者时,我只是设置一个观察者来看孩子。@ each._needsUpdate。