在 javascript 中,获取或设置一个属性时进行某些处理的唯一方法是使用Object.defineProperty:
Object.defineProperty(person, "b", {
get : function() {
return person.firstName + ' ' + person.surname;
},
set : function(newValue) {
var names = newValue.split(' ');
person.firsname = names[0];
person.surname = names[1];
},
enumerable : true,
configurable : true
});
但这有一些缺点:
- 不是跨浏览器
- 没有绑定,换句话说,如果
firstname
或surname
更改,则依赖属性fullname
不会更改。
- 调用
person.name
whenperson
未定义,会抛出错误
- 不可能触发观察者,没有额外的代码并且知道依赖层次:
firstname
depends from fullname
,它可以是其他属性的依赖啊!
因此,Ember 具有“属性”的概念,称为计算属性。
可以通过两种方式声明:
foo: Ember.computed(function({
...
}).property(dependent keys);
或使用(默认)时Ember.ENV.EXTEND_PROTOTYPES = true
:
foo: function() {
...
}.property(dependent keys);
, 是必需的property(dependent keys)
,因为它告诉 ember 什么是在更改时将更新属性的属性。
fullname: function(key, value) {
// setter
if (value !== undefined) {
var names = value.split(' ');
this.set('firstname', names[0]);
this.set('surname', names[1]);
}
// always return the complete result, so nexts calls to this.get('fullname') will return the cached value
return this.get('firstname') + ' ' + this.get('surname');
}.property('firstname', 'surname')
使用它,您具有以下优势:
- 当更改
firstname
或更改surname
为新值时,fullname
会更改。
beforeObserves
改变值之前触发,改变值之后observes
触发。
- 任何引用某些属性的模板都会更新
- 对 person.get('firstname') 的多次调用将返回一个缓存值,从而节省处理。您可以使用禁用此功能
.property(..).volatile()
- 在访问 null 对象时避免 null 或 undefined 错误,例如:如果 person 或 dog 未定义,则
controller.get('person.dog.name')
返回。undefined
我希望它有帮助