Ответ 1
В 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
, когдаperson
равен undefined, сделать ошибку, которая будет выбрана - Невозможно вызвать наблюдателей, без дополнительного кода и знать иерархию зависимостей:
firstname
зависит отfullname
, и это может быть зависимость других свойств arghhh!
В связи с этим у 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 или undefined при доступе к нулевым объектам вроде:
controller.get('person.dog.name')
возвращаетundefined
, если человек или собака undefined.
Я надеюсь, что это поможет