Подтвердить что ты не робот

Вычисляемые свойства в базовой линии

У меня есть сценарий, в котором данные, обрабатываемые клиентом, представлены и взаимодействуют с ним по-другому, чем на сервере.

Рассмотрим следующий ресурс 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()?

4b9b3361

Ответ 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 (или аналогичный) для создания производного геттера для продолжительности