#6 觀察者

英文原版:https://guides.emberjs.com/v2.13.0/object-model/observers/

【注】觀察者很容易被Ember新手濫用。由於觀察者本身就比較耗性能,所以在面對大多數情況時,推薦使用計算屬性。

觀察者支持觀察任何屬性,包括計算屬性。

觀察者其實就是一個監聽器,它能反映出被其監聽的屬性的變化。當你需要在被觀察的目標屬性完成同步操作後做些事情,那麼它尤其有用。

你可以通過使用Ember.observer來對目標屬性進行觀察:

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

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

  fullNameChanged: Ember.observer('fullName', function() {
    // deal with the change
    console.log(`fullName changed to: ${this.get('fullName')}`);
  })
});

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

// observer won't fire until `fullName` is consumed first
person.get('fullName'); // "Yehuda Katz"
person.set('firstName', 'Brohuda'); // fullName changed to: Brohuda Katz

上面的代碼中,由於fullName依賴於firstName,所以更新firstName也會觸發觀察者。

觀察者與異步

觀察者目前是同步的。這意味着它會在被觀察的屬性發生變化後立即執行。正因爲如此,它可以很方便的幫你調試沒有乖乖同步的屬性的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'));
  })
});

但是這個同步的行爲同時也會導致當對多個屬性進行觀察時,觀察者會被觸發多次。

爲了繞過這個問題,建議你使用Ember.run.once().這會保證在整個流程中,觀察者只會觸發一次,並且在所有觀察對象都做出變化後才執行。

觀察者與對象初始化

一般情況下,觀察者僅會在對象初始化完成後纔會觸發。

但是如果你需要觀察對象初始化過程,比如init過程,那麼你需要用on來對init過程進行觀察:

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

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

未調用的計算屬性不能觸發觀察者

如果一個計算屬性從來沒有被get()調用過,那麼就算觀察者對它進行監聽了也無法被觸發

如果你需要觀察一個計算屬性,但是又不想立刻檢索它,那就再init()用get它。

在類定義代碼外部添加觀察者

你同時也可以在類定義代碼的外部來添加觀察者:

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

本節完

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章