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

Я пытаюсь сделать следующее:

  1. Получить данные с сервера
  2. Добавьте к моделям индекс с отсчетом от нуля до того, как представления будут уведомлены.
  3. Наконец, запустите события «рендеринга» для просмотров.

Я пытался сделать это, используя обратный вызов успеха в коллекции

Просмотреть до

initialize: () ->
  @collection.on 'reset', @render, this

render: () -> ...render code...

Сбор до

search: () ->
  @fetch { 
    success: @fetch_success
  }  

fetch_success: () ->
  for i in [0...collection.models.length]
    collection.models[i].set('go_index', i)

Делая что-то таким образом, представления запускали свои события рендеринга до того, как коллекция была обновлена ​​обратным вызовом успеха. Решение, которое я придумал, заключалось в том, чтобы представления прослушивали событие fetched, а затем запускали коллекцию, которая после успешного изменения коллекции:

Просмотреть после

initialize: () ->
  @collection.on 'fetched', @render, this

render: () -> ...render code...

Сбор после

initialize: () ->
  @on 'reset', @add_index_and_notify, this

add_index_and_notify: () ->
  for i in [[email protected]]
    @models[i].set('go_index', i)
  @trigger('fetched')

Это отлично работает, мне просто интересно, является ли это самым элегантным способом сделать это или есть встроенный способ, который мне не хватает.

ОБНОВЛЕНИЕ 15 марта

Я придумал более чистое решение, которое не требует, чтобы представление выполняло какую-либо грязную работу, и мне не нужно создавать настраиваемое событие. Хитрость заключается в прослушивании события sync (которое срабатывает после reset)

Посмотреть окончательный вариант

initialize: () ->
  @collection.on 'sync', @render, this

render: () -> ...render code...

Финал коллекции

initialize: () ->
  @on 'reset', @add_index, this

add_index: () ->
  for i in [[email protected]]
    @models[i].set('go_index', i)

Надеюсь, этот шаблон может помочь кому-то в поиске в будущем.


person Dan Caddigan    schedule 13.03.2013    source источник


Ответы (3)


Я уже опубликовал решение в исходном вопросе, но решил, что официально опубликую ответ:

Более чистое решение не требует, чтобы представление выполняло какую-либо грязную работу, и не требует пользовательского события. Хитрость заключается в прослушивании события sync (которое срабатывает после reset)

Посмотреть окончательный вариант

initialize: () ->
  @collection.on 'sync', @render, this

render: () -> ...render code...

Финал коллекции

initialize: () ->
  @on 'reset', @add_index, this

add_index: () ->
  for i in [[email protected]]
    @models[i].set('go_index', i)

Надеюсь, этот шаблон может помочь кому-то в поиске в будущем.

person Dan Caddigan    schedule 15.03.2013
comment
У меня есть аналогичный вариант использования, это было полезно. Теперь мне просто интересно, есть ли какие-либо последствия при использовании «синхронизации» вместо «сброса». - person raine; 19.05.2013

Ваше представление должно получать как модель, так и ее индекс отдельно от коллекции, потому что индекс на самом деле не является частью самой записи модели. Попробуйте, чтобы ваше представление использовало collection.each для циклического перебора моделей, так как функция обратного вызова получит model, index, collection в качестве параметров. Помните, что представление может передавать в свой шаблон не только одну модель.

class CollectionView1 extends Backbone.View
  render: =>
    $el = @$el
    $el.empty()
    @collection.each (model, index) ->
      modelView = new ModelView1 {model, index}
      $el.append modelView.render().el
    return this
person Peter Lyons    schedule 13.03.2013
comment
Проблема в том, что невозможно сказать, какое представление получит reset первым. Тяжелая работа должна выполняться в коллекции, чтобы не было зависимости от представлений. Я также рассмотрю переопределение синтаксического анализа, но я думаю, что придумал более простой подход. - person Dan Caddigan; 16.03.2013
comment
Хм? Это не имеет смысла. Как вы думаете, почему так важно, какое представление получает reset первым? Это не так. Дублирование информации о коллекции (индекса) в модель — плохая идея, которая в конечном итоге принесет больше вреда, чем пользы. Я обновлю свой ответ, чтобы уточнить. - person Peter Lyons; 16.03.2013

Почему бы вам не прослушать событие добавления коллекции..

initialize: function() {
  this.listenTo(this.collection, 'reset', this.render);
  this.listenTo(this.collection , 'add' , this.add_index_and_notify);
  this.index = 0;
},

add_index_and_notify: function(model){
    model.set({go_index : this.index++}, {silent : true});
    // Render the model here
},

render: function(){
   this.$el.empty().append(Your template);
   this.index= 0;
   _.each(this.collection.models, function(model){
         this.add_index_and_notify(model);
   }
}
person Sushanth --    schedule 14.03.2013
comment
Это интересный подход, но проблема в том, что есть 2 отдельных представления (карта Google и соответствующий список, если вам интересно), которые будут использовать этот индекс. Кажется, что это может быть в любом из этих представлений. Это не кажется чище, чем то, что я делал раньше. Я придумал лучший способ - прослушивая событие 'sync', которое запускается после сброса. - person Dan Caddigan; 16.03.2013