Представление магистрали не отображается правильно при последующих вызовах обработчика маршрута

У меня возникла проблема с успешным рендерингом представления backbone.js из обработчика маршрута (приложения браузера).

Мой модуль javascript в настоящее время настроен следующим образом:

$(function () { // DOM ready
    myModule.Init();
});

var myModule = (function () {

// Models
    var DonorCorpModel = Backbone.Model.extend({ });

// Collections
    var DonorCorpsCollection = Backbone.Collection.extend({ model : DonorCorpModel });

// Views
    var DonorCorpsListView = Backbone.View.extend({
        initialize : function () {
            _.bindAll(this, 'render');
            this.template = Handlebars.compile($('#pre-sort-actions-template').html())
            this.collection.bind('reset', this.render);
        },
        render : function () {
            $(this.el).html(this.template({}));

            this.collection.each(function (donorCorp) {
                var donorCorpBinView = new DonorCorpBinView({
                    model : donorCorp,
                    list : this.collection
                });

                this.$('.donor-corp-bins').append(donorCorpBinView.render().el);
            });

            return this;
        }
    });

    var DonorCorpBinView = Backbone.View.extend({
        tagName : 'li',
        className : 'donor-corp-bin',
        initialize : function () {
            _.bindAll(this, 'render');
            this.model.bind('change', this.render);
            this.template = Handlebars.compile($('#pre-sort-actions-donor-corp-bin-view-template').html());
        },
        render : function () {
            var content = this.template(this.model.toJSON());
            $(this.el).html(content);
            return this;
        }
    })

// Routing
    var App = Backbone.Router.extend({
        routes : {
            '' : 'home',
            'pre-sort' : 'preSort'
        },

        initialize : function () {
            // ...
        },

        home : function () {
            // ...
        },

        preSort : function () {
            if (donorCorps.length < 1) {
                donorCorps.url = 'http://my/api/donor-corps';
                donorCorps.fetch();
            }

            var donorCorpsList = new DonorCorpsListView({ collection : donorCorps }).render().el;
            $('#document-action-panel').empty().append(donorCorpsList);

            // ...
        }
    });

// Private members
    var app;
    var donorCorps = new DonorCorpsCollection();

// Public operations
    return {
        Init: function () { return init(); }
    };

// Private operations
    function init () {
        app = new App();
        Backbone.history.start({ root: '/myApp/', pushState: true });
        docr.navigate('/', { trigger: true, replace: true});
    }

}(myModule || {}));

Все работает нормально, когда я запускаю приложение... оно переходит к домашнему виду, как и ожидалось. У меня настроены ссылки с обработчиками для надлежащего перехода к различным маршрутам, и когда я запускаю app.navigate('pre-sort', { trigger: true, replace: true}), он работает нормально и отображает ожидаемые элементы в списке, как и ожидалось.

Проблема возникает, когда я пытаюсь вернуться назад в исходное представление, а затем снова вернуться в представление предварительной сортировки... элементы в списке не отображаются на экране, как я ожидая их. Я просто получаю пустой pre-sort-actions-template без добавления к нему дочерних представлений. Я просмотрел код и вижу, что коллекция заполнена и элементы есть... но по какой-то причине мой код не отображает их в представлении должным образом, и я не могу понять почему или что я делаю неправильно. Любые идеи?? Я новичок в backbone, поэтому я уверен, что этот код написан не совсем правильно... конструктивная обратная связь приветствуется. Спасибо.


person Bob Yexley    schedule 26.06.2012    source источник
comment
Возможно, у вас есть проблема с контекстом в DonorCorpsListView.render, когда this.$ становится пустым в итераторе .each?   -  person rjz    schedule 26.06.2012
comment
@rjz, не могли бы вы рассказать об этом немного подробнее. Похоже, что в этой области что-то идет не так, но я не совсем уверен, что именно. Какая у меня будет проблема с контекстом? Коллекция, которую я повторяю, заполнена данными... в чем проблема?   -  person Bob Yexley    schedule 26.06.2012


Ответы (1)


как код отображает его в представлении после возвращения домой, а затем снова выполняет предварительную сортировку? не могли бы вы предоставить некоторые подробности об этом? повторяющиеся элементы? пустой вид?

Кроме того, мне нравится сохранять индекс моих подпредставлений при их рендеринге, чтобы родительское представление всегда могло получить к ним доступ независимо от области видимости. Я нашел действительно хорошую технику для этого здесь: Советы по Backbone.js: уроки из окопов

Краткий обзор шаблона, о котором я говорю, выглядит следующим образом:

var ParentView = Backbone.View.extend({
    initialize: function () {
        this._viewPointers = {};
    },
    render: function (item) {
        this._viewPointers[item.cid] = new SubView ({
            model: item
        });
        var template = $(this._viewPointers[item.cid].render().el);
        this.$el.append(template);
    }
});

var SubView = Backbone.View.extend({
    initialize: function () {
        this.model.on("change", this.render, this);
    },
    render: function () {
        this.$el.html( _.template($('#templateId').html(), this.model.attributes) );
        return this;
    }
});

Я понимаю, что этот ответ довольно «широкий», но будет легче ответить более подробно, если я смогу точно понять проблему с рендерингом. Надеюсь, что это хоть как-то поможет :)

person jandvik    schedule 26.06.2012
comment
Да, я должен был включить эту информацию для начала ... слишком расплывчато ... извините ... я это исправлю. - person Bob Yexley; 26.06.2012
comment
Происходит то, что вы создаете новое представление каждый раз, когда обращаетесь к этому параметру маршрутизации, не уничтожая его до этого. Кроме того, представление находится в локальной области действия этой функции маршрутизации, поэтому нет хорошего способа его уничтожить. Если все ваше приложение находится в одном пространстве имен, т. е. var app = {}, а все остальное находится в приложении в качестве параметров, вы всегда сможете получить доступ к тому конкретному экземпляру, который уже был инициализирован, а не создавать каждый раз новое представление. Также коллекция, которую вы в нее передаете, никогда не сбрасывается, она просто каждый раз создает все новое. - person jandvik; 26.06.2012
comment
и вместо var DonorCorpsList = new DonorCorpsListView({ collection : DonorCorps }).render().el; вы можете сделать app.donorCorpsList.reset(donorCorps); который вызовет сброс и обновит представление, а не повторно инициализирует его. Инициализируйте app.donorCorpsList в первый раз, когда он понадобится, если он уже есть, просто обновите его :) - Надеюсь, это поможет! - person jandvik; 26.06.2012
comment
наконец, чтобы сохранить область видимости при инициализации представления: this.collection.bind('reset', this.render); должно быть this.collection.bind('reset', this.render, this); - если не this внутри this.render относится к коллекции, а не к представлению. - person jandvik; 26.06.2012
comment
Аминь reset/не создавать заново! - person rjz; 26.06.2012
comment
Что ж, я думал, что разобрался с вашими предложениями, но в Backbone.View нет метода сброса, так что это не помогает. Кроме того, я пытался избежать сброса коллекции, так как в контексте этого приложения она будет доступна только для чтения, поэтому она не будет изменена, поэтому ее сброс не казался уместным, особенно учитывая, что сброс без аргументов просто опустошает коллекцию. Тааак... Я до сих пор не уверен, что мне здесь не хватает. - person Bob Yexley; 26.06.2012
comment
документация Backbone .reset Сброс следует использовать для коллекций, а не для представления. Вы можете прослушивать событие Reset в представлении в разделе инициализации. this.collection.on('reset', this.doThis, this); и соответствующим образом перестроить представление. ИЛИ вы можете использовать магистральный маршрутизатор, чтобы скрыть/показать представления и просто обойти проблему вместе. Сброс является предпочтительным вариантом. - person jandvik; 28.06.2012