EmberJS,了解DS模型生命周期

时间:2016-02-01 20:43:46

标签: ember.js ember-data

我正在尝试监控DS模型的状态更改。

我在文档中找到了有趣的标志:

它们在模板中正常工作,我可以使用{{#if model.isLoading}}Is Loading{{/if}},例如。

但令人不安的是,这些标志中的观察者具有非常随机的行为。例如,我发现平面isSaving上的观察者根本不起作用。但是标志isReloading上的观察者非常有效。

在这里,我有一个完整的例子,说明我到目前为止所尝试过的事情。我已将此 Mixin 添加到我的模型

// app/models/mixins/loading-monitoring
import Ember from 'ember';

export default Ember.Mixin.create({
  isReloadingDidChange: Ember.observer('isReloading', function() {
    console.log('LOG: isReloadingDidChange', this.get('id'), this.get('isReloading'));
  }),

  isSavingDidChange: Ember.observer('isSaving', function() {
    console.log('LOG: isSavingDidChange', this.get('id'), this.get('isSaving'));
  }),

  isLoadingDidChange: Ember.observer('isLoading', function() {
    console.log('LOG: isLoadingDidChange', this.get('id'), this.get('isLoading'));
  }),

  isLoadedDidChange: Ember.observer('isLoaded', function() {
    console.log('LOG: isLoadedDidChange', this.get('id'), this.get('isLoaded'));
  }),

  onInit: Ember.on('init', function() {
    console.log('LOG: init', this.get('id'));
  }),

  onDidLoad: Ember.on('didLoad', function() {
    console.log('LOG: onDidLoad', this.get('id'));
  }),
});

我尝试调用所有这些观察者,但只触发了一些

> $E.toString()
  "<reports-dashboard-client-app@route:application::ember1553>"
> var report; $E.store.findRecord('report', 14).then(function(r) { report = r });
  Promise {_id: 438, _label: undefined, _state: undefined, _result: undefined, _subscribers: Array[0]}
  LOG: init 14
  XHR finished loading: GET "http://myapi.com/reports/14".
  LOG: onDidLoad 14
> report.toString()
  "<reports-dashboard-client-app@model:report::ember1554:14>"
> report.get('title')
  "new title"
> report.set('title', 'title modified')
  "title modified"
> report.save()
  Class {__ember1453996199577: null, __ember_meta__: Meta}
  XHR finished loading: PUT "http://myapi.com/reports/14".send 
> report.reload()
  LOG: isReloadingDidChange 14 true
  Class {__ember1453996199577: null, __ember_meta__: Meta}
  XHR finished loading: GET "http://myapi.com/reports/14".send
  LOG: isReloadingDidChange 14 false

我缺少什么?
有什么方法可以观察模型的状态并对变化做出反应:加载准备

1 个答案:

答案 0 :(得分:11)

'isLoading','isLoaded'和'isSaving'属性都是作为计算属性实现的。在Ember中,计算属性是惰性的,在使用.get首次请求或在模板中显示之前,不会计算它们的状态。因此,尽管概念上我们作为开发人员可能知道isLoading的值正在改变,并且在调用record.get('isLoading')时将返回不同的值,但就Ember而言,isLoading的值是关注的。在某些代码明确要求Ember获取该值并且Ember花时间计算其状态之前,它是未定义的。

因此,当您使用Ember.observer来监视计算属性时,在某些其他代码尝试访问计算属性的值之前,它将无法检测到计算属性中的更改。

观察者还有一些你可能想要了解的其他问题。 @stefanpenner很好地谈论了他们的问题https://www.youtube.com/watch?v=vvZEddrClAQ以及为什么要谨慎使用它们。

为了让你的mixin触发观察者事件,你需要在某些地方访问这些属性。这样做的最佳位置似乎在onInit函数中。如果将this.getProperties('isReloading', 'isSaving', 'isLoading', 'isLoaded');添加到onInit函数,则Ember将计算这些值,并且当这些属性的值发生更改时,观察者将正确触发。

DS.Model生命周期

引擎盖下,Ember Data维护着状态机以达到记录。此状态机用于跟踪记录与服务器的关系。在较高的层面上,这些是Ember数据记录所在的状态:

  • 装载
    • 创建
      • 未提交
      • 飞行
    • 保存
    • 更新
      • 未提交
      • 飞行
  • 删除
    • 保存
    • 未提交
    • 飞行

empty是每条记录开始生命的状态。除此之外的其他事实empty并不是很重要。

loading当Ember Data首次从服务器请求数据时,是否存在记录的状态。

loaded一旦Ember Data从服务器收到有关记录的一些信息,状态就会被记录下来。它有许多子状态,用于跟踪本地记录是否已更改,但尚未保存到服务器。如果在客户端创建记录,它将直接置于loaded.created.uncommitted状态。

deleted是已删除记录的状态。 deleted.saved子状态表示服务器已确认删除此记录。 deleted.uncommitted子状态表示该记录已在本地删除,但尚未调用record.save()

记录的当前状态由记录上的currentState属性公开。 isLoadingisLoadedisSaving都是currentState.isLoadingcurrentState.isLoadedcurrentState.isSaving的别名,因为状态机中的每个州都为所有状态预定义了值这些属性。

我希望DS.Model状态机的这个解释有所帮助。

另外要检查的是DS.Model个实例上公开的生命周期事件挂钩。 http://emberjs.com/api/data/classes/DS.Model.html#event_becameError