我想观察对象属性的所有更改.
在以下示例中,如果更改了firstname或lastname,我希望personChanged观察者通知我.
但我想在所有对象属性上应用泛型(使用Ember.keys()??)如何用更通用的东西替换'firstname','lastname'?
在我的例子中:
personChanged被调用时firstname或lastname发生变化:
App.MyObject: Ember.Object.create({
firstname: 'first',
lastname: 'last',
personChanged: Ember.observer(function() {
console.log("person changed");
}, 'firstname', 'lastname')
})
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
解决方案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'
});
Run Code Online (Sandbox Code Playgroud)
初始化时MyObject,会观察对象上已存在的所有属性content,并且personChanged每次属性更改时都会调用该函数.但是,由于观察者急切地被解雇[1],因此该函数personChanged应该是幂等的,而示例中的函数则不是幂等的.下一个解决方案通过使观察者变得懒惰来解决这个问题.
解决方案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');
}
});
Run Code Online (Sandbox Code Playgroud)
这里唯一的变化是现在只在Ember Run循环结束时调用实际的观察者函数,这可能是您正在寻找的行为.
其他说明
这些解决方案使用ObjectProxy的,而不是限定的目的本身上的观测,以避免设置杂散观察员(如属性init,willDestroy等)或一个属性来观察的显式列表.
可以扩展此解决方案以通过覆盖setUnknownProperty代理来开始观察动态属性,以便在每次添加密钥时添加观察者content.在willDestroy将保持不变.
参考
[1]由于Asyn Observers,这可能会很快改变
您所拥有的是正确使用内联观察者,但您只是有一些语法错误。然而,使用关键字就更简单了observes。所以我在下面对你的例子做了一些调整。
App.MyObject: Ember.Object.create({
firstname: 'first',
lastname: 'last',
personChanged: function() {
//firstname or lastname changed
}.observes('firstname','lastname')
});
Run Code Online (Sandbox Code Playgroud)
注意:我在属性两边加了引号
来源: http: //emberjs.com/guides/object-model/observers/
| 归档时间: |
|
| 查看次数: |
7108 次 |
| 最近记录: |