Điều này có thể sử dụng một ObjectProxy
trong hai hương vị, tùy thuộc vào yêu cầu của bạn. Cả hai cách tiếp cận này chỉ khác nhau về thời gian và người quan sát gọi bao nhiêu lần và cả hai đều dựa vào số Ember.keys
.
HTML cho cả hai giải pháp đều giống nhau.
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>
Giải pháp 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'
});
Trong khi initialising MyObject
, tất cả tài sản mà đã tồn tại trên các đối tượng content
được quan sát, và các chức năng personChanged
được gọi là mỗi lần bất kỳ thay đổi tài sản. Tuy nhiên, kể từ khi các nhà quan sát bị sa thải háo hức [1], chức năng personChanged
phải là idempotent, mà chức năng đó không phải là. Các giải pháp tiếp theo sửa lỗi này bằng cách làm cho người quan sát lười biếng.
Giải pháp 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');
}
});
Sự thay đổi duy nhất ở đây là các chức năng quan sát thực tế hiện nay được gọi là chỉ the end of the Ember Run loop, mà có thể là hành vi bạn đang tìm kiếm.
ghi chú khác
Những giải pháp này sử dụng ObjectProxy
thay vì định quan sát trên đối tượng riêng của mình để tránh thiết lập các quan sát viên giả mạo (trên thuộc tính như init
, willDestroy
, vv) hoặc một explicit list of properties to observe.
Giải pháp này có thể được mở rộng để bắt đầu quan sát các thuộc tính động bằng cách ghi đè setUnknownProperty
trên proxy để thêm người quan sát mỗi lần khóa được thêm vào content
. willDestroy
sẽ vẫn giữ nguyên.
Reference
[1] Điều này có thể thay đổi nhanh chóng nhờ vào quan sát asyn
sẽ này http://stackoverflow.com/questions/11623645/ember-js-observer-for- tất cả giá trị/11679850 # 11679850 phù hợp với bạn? –