Вычисляемые свойства в базовой линии
У меня есть сценарий, в котором данные, обрабатываемые клиентом, представлены и взаимодействуют с ним по-другому, чем на сервере.
Рассмотрим следующий ресурс event
, возвращенный с сервера.
{
"id": 123,
"start_at": 1331336004906,
"end_at": 1331337704906
}
И следующий шаблон для редактирования:
<form>
<!-- Notice how date and time are separated in the interface -->
<input type="text" name="start_date" value="{{start_date}}" />
<input type="text" name="start_time" value="{{start_time}}" />
<!-- Instead of asking for an end date/time, we ask for the duration -->
<input type="text" name="duration" value="{{duration}}" />
<input type="submit" />
</form>
Как я буду относиться к start_date
, start_time
и duration
как к атрибутам моей модели Backbone, не отправляя их на сервер? Могу ли я изменить .toJSON()
?
Ответы
Ответ 1
Ваша модель должна соответствовать как можно ближе к тому, что у вас есть на стороне сервера. Поэтому придерживайтесь start_at
и end_at
. Это значительно упростит ваши операции sync()
.
В форме редактирования формы вы можете:
- Вычислить
start_date
, start_time
, duration
через простые функции и вызвать их в шаблоне.
- Преобразуйте в
start_at
и end_at
при отправке.
Ответ 2
Я использую комбинацию функции initialize() вместе с прослушивателями событий изменений для обновления полученных атрибутов. Идея заключается в том, чтобы сначала вычислить атрибуты при инициализации модели, а во-вторых, чтобы модель прослушивала свои собственные изменения и соответствующим образом обновляла атрибуты.
Мое решение выглядит примерно так:
MyModel: Backbone.Model.extend({
initialize: function() {
this.updateDerivedAttributes();
this.on('change:start_at', this.updateDerivedAttributes, this);
},
updateDerivedAttributes: function() {
this.set({
start_date: Utils.dateFromDate( this.get( "start_at" ) ),
start_time: Utils.timeFromDate( this.get( "start_at" ) ),
duration: Utils.youGetTheIdea()
}, {silent:true});
}
});
Ответ 3
Мы очень привыкли отправлять model.toJSON()
для подачи шаблона. И этот метод очень сложно перезаписать, потому что он используется другими компонентами.
Но мы можем подать шаблон с помощью настраиваемого метода model.toJSONDecorated()
, который может выглядеть следующим образом:
# in your Backbone.Model
toJSONDecorated: function(){
return
_.extend(
this.toJSON(),
{
start_date : Utils.dateFromDate( this.get( "start_at" ) ),
start_time : Utils.timeFromDate( this.get( "start_at" ) ),
duration : Utils.youGetTheIdea( :) )
}
);
}
Конечно, это ломает несколько шаблонов, я могу жить с ним, если вы этого не сделаете, вы можете переместить эту логику в класс Decorator
, как предложили люди в других ответах.
Ответ 4
У вас есть несколько вариантов:
-
Переопределить toJSON
, чтобы вернуть вычисленный duration
-
Создайте метод duration()
на базовой линии Model
. Единственный недостаток, который вы должны назвать по-разному (obj.duration()
вместо obj.get('duration')
). По вашему мнению, что руки obj.toJSON()
для вашего шаблона, смешайте в атрибуте duration
-
Используйте https://github.com/asciidisco/Backbone.Mutators (или аналогичный) для создания производного геттера для продолжительности