JSRUN 用代码说话

观察者

编辑教程

观察者

Ember可以检测任何属性的变化,包括计算属性。

观察者使用

Ember可以察觉所有属性的变化,包括计算属性。

观察者是非常有用的,特别是计算属性绑定之后需要同步的时候。 观察者经常被Ember开发过度使用。

Ember框架本身已经大量使用观察者,但是对于大多数的开发者面对开发问题时使用计算属性是更适合 的解决方案。

使用方式:可以用Ember.observer创建一个对象为观察者。

Observer对于Emberjs来说非常重要,前面你看到的很多代码都是与它有关系,计算属性之所以能更新也是因为它

Person = Ember.Object.extend({
  firstName: null,
  lastName: null,

  fullName: Ember.computed('firstName', 'lastName', function() {
    return this.get('firstName') + " " + this.get('lastName');
  }),

  //  当fullName被改变的时候触发观察者
  fullNameChange: Ember.observer('fullName', function() {
    console.log("The fullName is changed by caller");
    //return this.get('fullName');
  })
});

var person = Person.create({
  firstName: 'chen',
  lastName: 'ubuntuvim'
});
// 如果被观察的计算属性还没执行过get()方法不会触发观察者
console.log('fullName = ' + person.get('fullName'));  
//  fullName是依赖firstName和lastName的,这里改变了firstName的值,计算属性会自动更新,
//  fullName被改变了所以会触发观察者
person.set('firstName', 'change firstName value');  // 观察者会被触发
console.log('fullName = ' + person.get('fullName'));

fullName是依赖firstName和lastName的,调用set()方法改变了firstName的值,自然的导致fullName的值也被改变了,fullName变化了就触发观察者。从执行的结果就可以看出来;

Ember还为开发者提供了另一种使用观察者的方式。这种方式使你可以在类定义之外为某个计算属性增加一个观察者。

person.addObserver('fullName', function() {
    // deal with the change…
});

观察者与异步

目前,观察者在Ember中是同步的(不是笔误,官网就是这么说的Observers in Ember are currently synchronous.)。这就意味着只要计算属性一发生变化就会触发观察者。也因为这个原因很容易就会引入这样的bug在计算属性没有同步的时候。比如下面的代码;

Person.reopen({
  lastNameChanged: Ember.observer('lastName', 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'));
  })
});

然而由于同步的原因如果你的的观察者同时观察多个属性,就会导致观察者执行多次。

person = Ember.Object.extend({
  firstName: null,
  lastName: null,

  fullName: Ember.computed('firstName', 'lastName', function() {
    return this.get('firstName') + " " + this.get('lastName');
  }),

  //  当fullName被改变的时候触发观察者
  fullNameChange: Ember.observer('fullName', function() {
    console.log("The fullName is changed by caller");
    //return this.get('fullName');
  })
});
Person.reopen({
  partOfNameChanged: Ember.observer('firstName', 'lastName', function() {
    //  同时观察了firstName和lastName两个属性
    console.log('========partOfNameChanged======');
  })
});
var person = Person.create({
  firstName: 'chen',
  lastName: 'ubuntuvim'
});

person.set('firstName', '[firstName]');
person.set('lastName', '[lastName]');

显然上述代码执行了两次set()所以观察者也会执行2次,但是如果开发中需要设置只能执行一次观察出呢?Ember提供了一个once()方法,这个方法会在下一次循环所有绑定属性都同步的时候执行。

Person = Ember.Object.extend({
  firstName: null,
  lastName: null,

  fullName: Ember.computed('firstName', 'lastName', function() {
    return this.get('firstName') + " " + this.get('lastName');
  }),

  //  当fullName被改变的时候触发观察者
  fullNameChange: Ember.observer('fullName', function() {
    console.log("The fullName is changed by caller");
    //return this.get('fullName');
  })
});
Person.reopen({
  partOfNameChanged: Ember.observer('firstName', 'lastName', function() {
    //  同时观察了firstName和lastName两个属性
    //  方法partOfNameChanged本身还是会执行多次,但是方法processFullName只会执行一次
    console.log('========partOfNameChanged======');  //  
    Ember.run.once(this, 'processFullName');
  }),
  processFullName: Ember.observer('fullName', function() {
    // 当你同时设置多个属性的时候,此观察者只会执行一次,并且是发生在下一次所有属性都被同步的时候
    console.log('fullName = ' + this.get('fullName'));
  })
});

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

person.set('firstName', '[firstName]');
person.set('lastName', '[lastName]');

观察者与对象初始化

观察者一直到对象初始化完成之后才会执行。 如果你想观察者在对象初始化的时候就执行你必须要手动调用Ember.on()方法。这个方法会在对象初始化之后就执行。

Person = Ember.Object.extend({
  salutation:null,
  init() {
    this.set('salutation', 'hello');
    console.log('init....');
  },
  salutationDidChange: Ember.on('init', Ember.observer('salutation', function() {
    console.log('salutationDidChange......');
  }))
});

var p = Person.create();
p.get('salutationDidChange');  //  output > init....  salutationDidChange......
console.log(p.get('salutation'));  // output > hello
p.set('salutation');  //  output > salutationDidChange......

未获取过值的计算属性不会触发观察者

JSRUN闪电教程系统是国内最先开创的教程维护系统, 所有工程师都可以参与共同维护的闪电教程,让知识的积累变得统一完整、自成体系。 大家可以一起参与进共编,让零散的知识点帮助更多的人。
X
支付宝
9.99
无法付款,请点击这里
金额: 0
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间
如有疑问请联系QQ:565830900
正在生成二维码, 此过程可能需要15秒钟