Ember学习(6):Observers

英文原址:http://emberjs.com/guides/object-model/observers/


Ember支持监听任何属性,包括计算型属性。你可以通过对函数使用observes来针对一个对象创建observer。

Person = Ember.Object.extend({
  // these will be supplied by `create`
  firstName: null,
  lastName: null,

  fullName: function() {
    var firstName = this.get('firstName');
    var lastName = this.get('lastName');

    return firstName + ' ' + lastName;
  }.property('firstName', 'lastName'),

  fullNameChanged: function() {
    // deal with the change
  }.observes('fullName').on('init')
});

var person = Person.create({
  firstName: 'Yehuda',
  lastName: 'Katz'
});

person.set('firstName', 'Brohuda'); // observer will fire
因为fullName计算型属性依赖firstName属性,更新firstName也会触发fullName的observer。

观察者和异步

目前Ember中Observer都是同步的,这意味着observer方法会在他们观察的属性被改变的当时就被触发,因为这个原因,当属性不是同步方式使用时,容易引入一些bug。

Person.reopen({
  lastNameChanged: function() {
    // The observer depends on lastName and so does fullName. Because observers
    // are synchronous, when this function is called the value of fullName is
    // not updated yet so this will log the old value of fullName
    console.log(this.get('fullName'));
  }.observes('lastName')
});
上面的observer依赖lastName,也需要调用fullName。因为observer是同步的,当这个函数被调用时,fullName的值还没有来得及更新,因此它会打印出fullName的旧值。

这种同步的机制也会导致同一个observer被触发多次,当这个observer同时监听多个属性时。

Person.reopen({
  partOfNameChanged: function() {
    // Because both firstName and lastName were set, this observer will fire twice.
  }.observes('firstName', 'lastName')
});

person.set('firstName', 'John');
person.set('lastName', 'Smith');

为了避免这样的问题,你应该使用Ember.run.once。这会保证任何你需要做的事情只会被执行一次,当所有绑定都是同步方式时,只在下一次run loop中发生一次。 (这里还是有点不太理解,没有使用过,回头理解的更透彻了,再细说)

Person.reopen({
  partOfNameChanged: function() {
    Ember.run.once(this, 'processFullName');
  }.observes('firstName', 'lastName'),

  processFullName: function() {
    // This will only fire once if you set two properties at the same time, and
    // will also happen in the next run loop once all properties are synchronized
    console.log(this.get('fullName'));
  }
});

person.set('firstName', 'John');
person.set('lastName', 'Smith');

观察者和对象初始化

只有一个对象的初始化完成了后,observer才会被触发。如果你需要observer在初始化发生时也被触发,你不能依赖set方法的副作用,你需要使用.on('init')来说明这个observer在初始化时也需要被触发。

App.Person = Ember.Object.extend({
  init: function() {
    this.set('salutation', "Mr/Ms");
  },

  salutationDidChange: function() {
    // some side effect of salutation changing
  }.observes('salutation').on('init')
});

没有被调用的计算型属性不会触发观察者

如果你从来没有对一个计算型属性使用get方法,它的observer永远也不会被触发,即使是该计算型属性依赖的属性发生了变化。你可以想象成它的值从一个unknown值变成另外一个。
这通常都不会影响应用的代码,因为计算型属性通常基本上被观察的同时也会被访问。举个例子,你访问了一个计算型属性的值,将它插入了HTML DOM(或者使用D3画出来),然后你监听它,当它改变时,你可以更新DOM。
如果你需要监听一个计算型属性,但是却不马上读取该计算型属性,你可以在init方法中读取它。

不使用Prototype扩展

如果你没有使用Ember的Prototype扩展,那么你可以使用Ember.observer方法来定义observer:
Person.reopen({
  fullNameChanged: Ember.observer('fullName', function() {
    // deal with the change
  })
});

在类定义外面使用

你也可以在一个类定义的外面通过使用addObserver方法来给某个对象添加observer:
person.addObserver('fullName', function() {
  // deal with the change
});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值