Backbone.js предоставляет минималистичный каркас для построения клиентских приложений, где основными строительными блоками являются Models, Collections, Views и Router. Одной из частых задач при работе с моделями является создание свойств, которые зависят от других атрибутов модели. Для решения этой задачи используются концепции computed properties и derived attributes.
Derived attributes — это атрибуты модели, значения которых вычисляются на основе других атрибутов. Они не хранятся напрямую в объекте модели, а формируются динамически при доступе. Такой подход позволяет избежать дублирования данных и поддерживать модель в согласованном состоянии.
Пример:
var Person = Backbone.Model.extend({
defaults: {
firstName: '',
lastName: ''
},
fullName: function() {
return this.get('firstName') + ' ' + this.get('lastName');
}
});
var person = new Person({ firstName: 'Иван', lastName: 'Иванов' });
console.log(person.fullName()); // Иван Иванов
Здесь fullName является derived
attribute, зависящим от firstName и
lastName. Он пересчитывается при каждом вызове функции.
Computed properties — более продвинутый способ
работы с производными значениями. Основное отличие от обычных derived
attributes состоит в том, что они могут автоматически
обновляться и триггерить события при изменении зависимых
атрибутов. Backbone.js не предоставляет встроенной поддержки
computed properties, но их можно реализовать через расширения модели и
прослушивание событий change.
Пример реализации:
var Person = Backbone.Model.extend({
defaults: {
firstName: '',
lastName: ''
},
initialize: function() {
this.on('change:firstName change:lastName', this.updateFullName);
this.updateFullName();
},
updateFullName: function() {
this.set('fullName', this.get('firstName') + ' ' + this.get('lastName'), { silent: true });
this.trigger('change:fullName');
}
});
var person = new Person({ firstName: 'Иван', lastName: 'Иванов' });
person.on('change:fullName', function(model, value) {
console.log('Full name UPDATEd:', value);
});
person.se t('firstName', 'Пётр'); // Full name UPDATEd: Пётр Иванов
Здесь fullName автоматически пересчитывается при
изменении зависимых атрибутов. Использование
{ silent: true } предотвращает зацикливание событий.
При создании computed properties важно учитывать:
Пример оптимизации:
updateFullName: function() {
var newFullName = this.get('firstName') + ' ' + this.get('lastName');
if (this.get('fullName') !== newFullName) {
this.set('fullName', newFullName, { silent: true });
this.trigger('change:fullName');
}
}
Это предотвращает ненужное триггерение события при неизменном значении.
В Backbone.js Views часто подписываются на изменения атрибутов модели:
var PersonView = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, 'change:fullName', this.render);
},
render: function() {
this.$el.text(this.model.get('fullName'));
return this;
}
});
var view = new PersonView({ model: person });
person.set('lastName', 'Петров'); // Автоматическое обновление текста
Computed properties позволяют держать View синхронизированным с моделью без ручного вызова функций для пересчёта данных.
Существуют сторонние библиотеки и плагины, которые упрощают работу с computed properties в Backbone.js, например:
Использование таких библиотек снижает объем ручного кода и повышает читаемость.
Computed properties и derived attributes обеспечивают чистую и предсказуемую логику данных, облегчая построение интерактивных и поддерживаемых клиентских приложений на Backbone.js.