коллекция магистралей, сохраняющая порядок сортировки по мутации модели - PullRequest
7 голосов
/ 02 апреля 2011

Если у меня есть коллекция с компаратором. (в кофейном тексте)

class Words extends Backbone.collection
    comparator: (word)->
        word.get('score')

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

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

Возможно, я бы попробовал удалить мутированный предмет и затем добавьте его снова.

Есть предложения?

Ответы [ 2 ]

5 голосов
/ 03 апреля 2011

Похоже, что код рендеринга крайне неэффективен по одной простой причине: Манипулирование DOM стоит дорого. По возможности, вы должны манипулировать DOM один раз, а не несколько раз.Вся остальная оптимизация в JavaScript / CoffeeScript является вторичной.

Вот выдающийся код (из сущности, на которую ссылается второй комментарий к ответу Амберта):

refresh: ->
    @list.listview("refresh")

appendWord: (word)->
    wv = new WordView({model: word}).render().el
    @list.append( wv )
    @refresh()

render: ->
    @list.html("")
    @model.each (word) => @appendWord(word)
    @refresh()

Итак, на render сначала HTML-код списка очищается;затем для каждого слова HTML списка очищается и элемент управления обновляется!

Я не знаком с jQuery Mobile, поэтому не уверен, чтоосновное наказание налагается на append (как в jQuery) или на listview('refresh'), но цикл легко переписать, чтобы избежать обоих, и также удалить некоторые функции, определяющие / вызывающие накладные расходы:

render: ->
  html = []
  @model.each (word) ->
    html.push(new WordView(model: word).render().el)
  @list.empty().append(html)

Теперь у вас есть только один html установщик и один refresh вызов, а не один html установщик, n append и n + 1 refresh звонки!

0 голосов
/ 02 апреля 2011

Как насчет того, чтобы связать все исходные модели Слова для сортировки по событию изменения, а затем связать то же самое по событию добавления в коллекцию?

_(self).models.each(model) { model.bind('change', self.sort) } // bind on the model add as well

Backbone.Collection.sort вызывает обновлениеИтак, просто:

this.bind('refresh', this.refresh)

Что касается вашего беспокойства по поводу эффективности, что вы подразумеваете под "весь список отсортирован по одному элементу?"Если у вас нет ТЫСЯЧИ элементов (и даже тогда, запустите некоторые тесты в различных браузерах, я уверен, что это будет чертовски быстро), это не должно иметь большого значения с современными браузерами / компьютерами

Если бы вы былидействительно обеспокоен этим, я думаю, вы можете использовать некоторые методы оптимизации для сортировки больших наборов.Например, отбросьте их в сегменты оценок (0-100, 100-500, 500-1000 и т. Д.), Затем сбросьте оценки в сегменте и выполняйте сортировку только в пределах корзины (фактический алгоритм сортировки выполняется для каждой реализации браузера, Backbone -или, скорее, подчеркивают, просто называет это).Вы можете гуглить по таким алгоритмам.Но это большая работа для небольшого выигрыша против увеличения сложности кода.

Опять же, вам понадобится много профилирования и сравнительного анализа, чтобы определить, действительно ли это того стоит.

...