2015-08-17 1 views
2

Я пытаюсь найти способ эффективно отображать отсортированную Marionette.CollectionView, отсортированную по нескольким атрибутам без изменения базовой коллекции Backbone. Для этого примера я использую «имя» и «онлайн» атрибуты, и хочу, чтобы мой CollectionView будет отображаться в 2-х частей:Эффективная коллекция Marionette CollectionView для нескольких атрибутов

  • онлайн, по алфавиту
  • офлайновых, по алфавиту

У меня есть одну коллекцию Backbone.Models и хотите использовать ее в моем веб-приложении. Поэтому наличие функции сортировки в моей коллекции мне не подходит.

Мой пример кода выглядит следующим образом:

var MyCollection = Backbone.Collection.extend({ 
    model:Backbone.Model 
}); 

var myCollection = new MyCollection(); 

myCollection.set([ 
    { name : 'Freddy', online : true }, 
    { name : 'Zorro', online : false }, 
    { name : 'Charlie', online : false }, 
    { name : 'Alice', online : true } 
]); 

var MyView = ... 
/* 
omitted for brevity, though my template is like 
<li>{{name}} {{#if online}}(Online){{/if}}</li> 
*/ 

var MyCollectionView = Marionette.Collection.extend({ 
    childView:MyView, 
    viewComparator: function (item1, item2) { 

    var item1Online = item1.get('online'); 
    var item2Online = item2.get('online'); 
    if (item1Online != item2Online) 
     return item1Online ? -1 : 1; 

    var item1Name = item1.get('name'); 
    var item2Name = item2.get('name'); 
    return item1Name.localeCompare(item2Name); 
    } 
}); 

var myCollectionView = new MyCollectionView({collection:myCollection}); 

appView.getRegion('example').show(myCollectionView); 

Я хотел бы, чтобы это будет отображаться как:

  • Алиса (онлайн)
  • Freddy (Online)
  • Чарли
  • Zorro

Это прекрасно, когда все данные добавляются в коллекцию сразу или добавляют/удаляют события, но если один из атрибутов обновлен в модели, которая уже находится в коллекции, представление не обновляется.


Если свойство «онлайн» Чарли изменилось на истину - например, выполнив.

charlieModel.set('online', true) 

Я хотел бы CollectionView, что вынесенное автоматически:

  • Алиса (онлайн)
  • Чарли (Интернет)
  • Freddy (Интернет)
  • Зорро

Любые предложения? Спасибо заранее.

+0

Я всегда задавался вопросом, что лучший способ сделать это в Backbone, но 1) страх не имея метод сортировки, это не так. 2) в сочетании с методом .clone(), вы можете свободно сортировать копию коллекции, не изменяя ее источник. – stolli

ответ

0

Команда марионеток рекомендуется наличие отдельного сбора Backbone за кулисами, а не с помощью viewComparator на CollectionView.

Использование reorderOnSort на CollectionView имело огромное значение (не менее 10-кратного ускорения) с точки зрения скорости рендеринга.

Этот параметр полезен, если у вас возникли проблемы с производительностью при использовании CollectionView. Без этой опции ваш CollectionView будет полностью перерисован, что может быть дорогостоящим, если у вас есть большое количество элементов или если ваш ChildViews сложный. Если эта опция активирована, при сортировке коллекции не будет повторной рендеринга, будут переупорядочены только узлы DOM .

Мой последний пример кода:

var MyView = Backbone.Marionette.ItemView.extend({ 
    modelEvents:{ 
    'change:name change:online': 'render' 
    }, 
    template:template 
    }); 

    var MyCollection = Backbone.Collection.extend({ 
    initialize : function(){ 
     this.on('change:name change:online', this.sort, this); 
    }, 
    comparator : function(item1, item2){ 
     var item1online = item1.get('online'); 
     var item2online = item2.get('online'); 
     if (item1online != item2online) 
     return item1online ? -1 : 1; 

     return item1.get('name').localeCompare(item2.get('name')); 
    } 
    }); 

    var myCollection = new MyCollection(); 

    var MyCollectionView = Marionette.CollectionView.extend({ 
    childView : MyView, 
    reorderOnSort : true 
    }); 

    var myCollectionView = new MyCollectionView({ 
    collection : myCollection 
    }); 

    appView.region('example').show(myCollectionView); 
0

Из backbone documentation

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

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

// for example in your collection 
initialize: function() { 
    this.on('change:name', function() { this.sort() }, this); 
}