這是可能使用兩個ObjectProxy
口味,根據您的要求。兩種方法的區別僅在於觀察者打電話的時間和次數,他們都依賴於Ember.keys
。
這兩種解決方案的HTML都是相同的。
HTML
<script type="text/x-handlebars" data-template-name="app">
Name: {{App.MyObject.firstname}} {{App.MyObject.lastname}}
<ul>
{{#each App.List}}
<li>{{this}}</li>
{{/each}}
</ul>
</script>
解決方案1
的jsfiddle:http://jsfiddle.net/2zxSq/
的Javascript
App = Em.Application.create();
App.List = [];
App.MyObject = Em.ObjectProxy.create({
// Your Original object, must be defined before 'init' is called, however.
content: Em.Object.create({
firstname: 'first',
lastname: 'last'
}),
// These following two functions can be abstracted out to a Mixin
init: function() {
var self = this;
Em.keys(this.get('content')).forEach(function (k) {
Em.addObserver(self.get('content'), k, self, 'personChanged')
});
},
// Manually removing the observers is necessary.
willDestroy: function() {
var self = this;
Em.keys(this.get('content')).forEach(function (k) {
Em.removeObserver(self.get('content'), k, self, 'personChanged');
});
},
// The counter is for illustrative purpose only
counter: 0,
// This is the function which is called.
personChanged: function() {
// This function MUST be idempotent.
this.incrementProperty('counter');
App.List.pushObject(this.get('counter'));
console.log('person changed');
}
});
App.ApplicationView = Em.View.extend({
templateName: 'app'
});
// Test driving the implementation.
App.MyObject.set('firstname', 'second');
App.MyObject.set('lastname', 'last-but-one');
App.MyObject.setProperties({
'firstname': 'third',
'lastname' : 'last-but-two'
});
雖然初始化MyObject
,其已經的content
對象上存在的所有屬性被觀察到的,並且每次函數personChanged
被稱爲任何的屬性更改。但是,由於觀察者急切地被觸發[1],所以功能personChanged
應該是idempotent,其中示例中的功能不是。下一個解決方案通過讓觀察者懶惰來解決這個問題。
解決方案2
的jsfiddle:http://jsfiddle.net/2zxSq/1/
的Javascript
App.MyObject = Em.ObjectProxy.create({
content: Em.Object.create({
firstname: 'first',
lastname: 'last'
}),
init: function() {
var self = this;
Em.keys(this.get('content')).forEach(function (k) {
Em.addObserver(self, k, self, 'personChanged')
});
},
willDestroy: function() {
var self = this;
Em.keys(this.get('content')).forEach(function (k) {
Em.removeObserver(self, k, self, 'personChanged');
});
},
// Changes from here
counter: 0,
_personChanged: function() {
this.incrementProperty('counter');
App.List.pushObject(this.get('counter'));
console.log('person changed');
},
// The Actual function is called via Em.run.once
personChanged: function() {
Em.run.once(this, '_personChanged');
}
});
這裏唯一的變化是,只有在the end of the Ember Run loop實際觀測功能現在被稱爲,這可能是你正在尋找的行爲。
其他說明
這些解決方案使用ObjectProxy
代替定義對象本身上的觀測,以避免設置雜散觀察員(性能如init
,willDestroy
,等)或explicit list of properties to observe。
通過覆蓋代理上的setUnknownProperty
開始觀察動態屬性,每次將密鑰添加到content
時添加觀察者,可以擴展此解決方案。 willDestroy
將保持不變。
參考
[1]這可能很快就改變得益於ASYN觀察員
將這項http://stackoverflow.com/questions/11623645/ember-js-observer-for-全部值/ 11679850#11679850爲你工作? –