英文原版: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
});
本節完