Вычисляемые свойства в Магистрали - PullRequest
17 голосов
/ 10 марта 2012

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

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

Ответы [ 4 ]

22 голосов
/ 31 октября 2012

Я использую комбинацию функции initialize () вместе с прослушивателями события change для обновления производных атрибутов.Идея состоит в том, чтобы сначала вычислить атрибуты при инициализации модели, а во-вторых, позволить модели прослушивать свои собственные изменения и соответствующим образом обновлять атрибуты.

Мое решение выглядит примерно так:

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});
    }
});
6 голосов
/ 13 марта 2012

Мы очень привыкли отправлять 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, как предлагали люди в других ответах.

5 голосов
/ 26 июня 2012

У вас есть несколько вариантов:

  • Переопределить toJSON для возврата вычисленного duration

  • Создание метода duration() на магистральной линии Model. Единственный недостаток, что вы должны называть его по-другому (obj.duration() вместо obj.get('duration')). С вашей точки зрения, что obj.toJSON() передает ваш шаблон, смешайте в атрибуте duration

  • Используйте https://github.com/asciidisco/Backbone.Mutators (или аналогичный) для создания производного геттера на длительность

4 голосов
/ 10 марта 2012

Ваша модель должна максимально соответствовать тому, что у вас на стороне сервера.Так что придерживайтесь start_at и end_at.Это значительно упростит ваши sync() операции.

В Просмотр формы редактирования вы можете:

  1. Вычислить start_date, start_time, duration через простые функции и вызывайте их в шаблоне.
  2. Преобразуйте в start_at и end_at при отправке.
...