Ответы пользователя по тегу Backbone.js
  • Как подключать встречные зависимости RequireJS?

    @xaseros Автор вопроса
    Если кому надо то вот дока

    requirejs.org/docs/api.html#circular

    Или решение для конкретного случая, когда Task требуется на этапе выполнения, а не на этапе декларирования состоит в том, чтобы объявить в замыкании имя Task, а запись в него элемента нужного компонента доверить той-же require

    define('model/stage', [
        'common/model'
    ], function(
        Common
    ){
        
        var Stage = {};
        
        var Task; // объявляем имя в замыкании
        
        require(['model/task'],function(module){ // просим загрузить нам указанный модуль, когда появится возможность
            Task = module;  // записываем в объявленное имя наш полученный модуль, но само собой, нет гарантии когда это произойдет
        });
    
    . . .
    Ответ написан
    Комментировать
  • Сортировка/фильтрация в Backbone?

    @xaseros
    Я считаю что полностью заново рендерить коллекцию при сортировке это вообще шаг назад от идеологии MVC. рендерить заново надо только то что изменилось.

    При сортировке или фильтрации, мы можем использовать умное обновление коллекций с сервера. Оно будет вызывать соответствующие события add, remove, change. На любой списочный интерфейс я завожу 4 "класса", например: CommentListViewClass, CommentItemViewClass, CommentCollectionClass, CommentModelClass.

    CommentCollection передаем в CommentListView, и вызываем CommentCollection.fetch()
    Собственно вся соль делается в CommentListView, его и прифожу.
    var CommentsListViewClass = Backbone.View.extend({
            initialize: function(options){
                this.templateData = options && options.templateData || {};
                this.listenTo(this.collection, "add", this.renderItem);
                this.listenTo(this.collection, "add remove sync", this.renderUpdate);
                this.listenTo(this.collection, "sync", this.resortItems);
                
                this.itemViews = [];
            },
            render: function(){
                this.$el.empty();
            },
            renderUpdate: function(){
                $('.comments_count').html(this.collection.length);
            },
            resortItems: function(){
                this.collection.each(_.bind(function(m,i){
                    var viewEl = this.$("."+m.cid);
                    this.placeItem(viewEl, m);
                }, this));
            },
            placeItem: function(itemEl, model){
                var index = _.indexOf(this.collection.models, model);
                //console.log(index, itemEl,model);
                if(index == 0){
                    console.log("#"+ index ,model.id, 'ontop');
                    this.$el.prepend(itemEl);
                } else {
                    var pIndex = index-1;
                    var cid = this.collection.models[pIndex].cid;
                    this.$el.find('.'+cid).after(itemEl);
                    console.log("#"+ index, model.id, "after " + this.collection.models[pIndex].id );
                }
            },
            renderItem: function(model, collection, options){
                var item = new CommentsItemViewClass({
                    model: model,
                    templateData: this.templateData
                });
                
                var itemEl = item.render();
                this.placeItem(itemEl, model);
            }
        });


    При добавлении новой модели в коллекцию, мы инициализируем новый вид элемента списка, передавая ему эту же модель. Это делает метод render_item.

    var item = new CommentsItemViewClass({
                    model: model,
                    templateData: this.templateData
                });
                //получим DOM-элемент вида
                var itemEl = item.render();


    Далее у каждого DOM-элемента (this.el) созданного вида добавляется класс (или любой другой атрибут) с cid той модели которую он отображает (это нужно сделать в шаблоне элемента). Затем нужно определить индекс (позицию) модели в коллекции, и разместить этот элемент под элементом вида предыдущей модели в коллекции (ну или воткнуть на самый верх если таковой не найден), этим далее и занимается метод placeItem .

    var index = _.indexOf(this.collection.models, model);
                //console.log(index, itemEl,model);
                if(index == 0){
                    this.$el.prepend(itemEl);
                } else {
                    var pIndex = index-1;
                    //cid предыдущей модели
                    var cid = this.collection.models[pIndex].cid;
                    this.$el.find('.'+cid).after(itemEl);
                }


    Аналогично при полном обновлении коллекции после sync, только пробежаться надо по всем моделям коллекции, дабы расставить все элементы по местам. Это уже resortItems.

    this.collection.each(_.bind(function(m,i){
                    var viewEl = this.$("."+m.cid);
                    this.placeItem(viewEl, m);
                }, this));
    Ответ написан
    Комментировать