Может ли Backbone визуализировать коллекцию в обратном порядке? - PullRequest
7 голосов
/ 19 марта 2012

Я использую концентратор Signalr для подписки на события на сервере.То, что событие отправляется в концентратор, это успешно добавление элемента в Marionette CollectionView.Это, в свою очередь, отображается в таблице.

Поскольку таблица событий по сути является блоттером, я хотел бы, чтобы события были в обратном порядке, и желательно, чтобы они сохраняли только n-количество событий.

Может ли Backbone «автоматически» повторно визуализировать коллекцию в обратном порядке?

Ответы [ 8 ]

11 голосов
/ 14 декабря 2012

Чтобы пройти сбор в обратном порядке, я обычно использую такую ​​конструкцию:

_.each(collection.last(collection.length).reverse(), function(model){ });
8 голосов
/ 09 мая 2012

В этой теме есть тема на https://github.com/marionettejs/backbone.marionette/issues/78

Хотя Backbone сохраняет коллекцию отсортированной после определения компаратора, как указывал @breischl, Marionette не выполняет повторную визуализацию CollectionView при изменении порядка,Фактически, Marionette прослушивает событие add в коллекции и добавляет новый ItemView.

Если вы хотите, чтобы ваш CollectionView всегда отображал элементы в обратном хронологическом порядке, и выхотите, чтобы новые элементы были добавлены с добавлением вместо с добавлением , а затем переопределите метод appendHtml в вашем CollectionView следующим образом:

var MyCollectionView = Backbone.Marionette.CollectionView.extend({
  appendHtml: function(collectionView, itemView){
    collectionView.$el.prepend(itemView.el);
  }
});

Если вы хотитечтобы иметь возможность вставлять в определенном месте, как @dira, упомянутое в комментарии, есть решение, размещенное по ссылке выше на github sberryman, которое я воспроизвожу здесь для удобства (отказ от ответственности: я не тестировал код ниже лично):

Измените appendHtml на:

appendHtml: function(collectionView, itemView) {
  var itemIndex;
  itemIndex = collectionView.collection.indexOf(itemView.model);
  return collectionView.$el.insertAt(itemIndex, itemView.$el);
}

И добавьте следующее, чтобы расширить jQuery, чтобы обеспечить insertAt функцию:

(function($) {
  return jQuery.fn.insertAt = function(index, element) {
    var lastIndex;
    if (index <= 0) return this.prepend(element);
    lastIndex = this.children().size();
    if (index >= lastIndex) return this.append(element);
    return $(this.children()[index - 1]).after(element);
  };
})(jQuery);
1 голос
/ 20 марта 2012

Из того, что вы описываете, вам не нужно повторно отображать коллекцию в обратном порядке. Просто добавьте событие для add в вашу коллекцию в этом представлении и вызовите функцию, которая отображает только что добавленный элемент и добавляет его к таблице.

this.collection.on('add', this.addItem);
1 голос
/ 20 марта 2012

Backbone автоматически сохраняет коллекции в отсортированном порядке.Если вы хотите использовать сортировку не по умолчанию, определите функцию comparator() в вашей коллекции, и она будет использовать ее вместо этого.Компаратор может принимать один или два аргумента, см. Подробности в документации Backbone .

Затем вы можете отобразить вашу коллекцию в цикле .each (), и она будет отображаться в правильном порядке.Однако добавление новых элементов в представление в отсортированном порядке зависит от вас.

1 голос
/ 19 марта 2012

Обычно вы выполняете рендеринг в вашем Backbone.View 'подклассе'. Итак, у вас есть что-то вроде:

render: function() {
  this.collection.each( function(model) {
    // some rendering of each element
  }, this );
}

this.collection предположительно является подклассом Backbone.Collection, и поэтому вы можете просто использовать underscore.js методы , чтобы получить его в любом порядке:

this.collection.reverse().each( ... )
this.collection.sort( function(m) { ... } ).each( ... )

1012 * Etc. *

Конечно, вы получаете один элемент из вашего бэкэнда, и вы хотите вставить его в нужное место без повторного рендеринга всего этого! Так что в этом случае просто перейдите к старой школе и вставьте свой ключ сортировки в качестве атрибута rel или data в элементах и ​​используйте его для insertAfter или аналогично jQuery в вашем renderNewItem (или аналогичном) методе.

0 голосов
/ 23 сентября 2015

Поскольку BackBone не поддерживает обратную итерацию коллекции (и это просто трата ресурсов на обратную или худшую сортировку коллекции), самый простой и быстрый способ - использовать цикл for с уменьшением индекса по моделям в коллекция.

for (var i = collection.length - 1; i >= 0; i--) {
    var model = collection.models[i];

    // your logic
}

Это не так элегантно, как сортировка или перестановка коллекции с помощью Underscore, но производительность намного лучше. Попробуйте сравнить различные циклы здесь , чтобы узнать, сколько стоит написать foreach вместо классического.

0 голосов
/ 18 марта 2015

Если вы используете lodash вместо подчеркивания, вы также можете сделать это:

_(view.collection.models).reverse();
0 голосов
/ 10 декабря 2014

Вы можете поменять свои модели в коллекции следующим образом ...

this.collection.models = this.collection.models.reverse()
...