【问题标题】:Backbone view not rendering correctly on subsequent calls to route handler在对路由处理程序的后续调用中,骨干视图未正确呈现
【发布时间】:2012-06-26 14:27:19
【问题描述】:

我在从路由处理程序(浏览器应用程序)成功渲染主干.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 渲染,没有附加任何子视图。我已经单步执行了代码,并且可以看到集合已填充并且项目在那里......但由于某种原因,我的代码没有正确地将它们呈现到视图中,我似乎无法弄清楚为什么或我做错了什么。有任何想法吗??我对骨干很陌生,所以我确信这段代码写得并不完全正确……欢迎提供建设性的反馈。谢谢。

【问题讨论】:

  • 您可能在 DonorCorpsListView.render 中遇到上下文问题,this.$.each 迭代器中出现空白?
  • @rjz 你能详细说明一下吗?似乎该区域出现了问题,但我不确定是什么。我会有什么样的上下文问题?我正在迭代的集合 填充了数据...有什么问题?

标签: backbone.js backbone-views backbone-routing


【解决方案1】:

回家后代码如何将其渲染到视图中,然后再次进行预排序?你能提供一些细节吗?重复项目?空视图?

另外,我喜欢在渲染子视图时保留它们的索引,以便父视图始终可以访问它们而不管范围如何。我在这里找到了一个非常好的技术:Backbone.js Tips : Lessons from the trenches

我所指的模式的简要概述如下:

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;
    }
});

我意识到这个答案相当“宽泛”,但如果我能理解渲染的确切问题,更具体的答案会更容易。无论如何,希望它有所帮助:)

【讨论】:

  • 是的,我应该一开始就包含这些信息……太模糊了……抱歉……我会更正那个。
  • 发生的情况是,每次访问该路由参数时,您都在创建一个新视图,而没有事先破坏它。此外,视图位于该路由功能的本地范围内,因此没有很好的方法来销毁它。如果您的整个应用程序存在于一个名称空间中,即“var app = {}”,而其他所有内容都作为参数存在于 app 下,那么您将始终能够访问已经初始化的确切实例,而不是每次都创建一个新视图.此外,您传递给它的集合永远不会重置,它只是每次都创建新的东西。
  • 而不是“var donorCorpsList = new DonorCorpsListView({ collection :donorCorps }).render().el;”你可以做“app.donorCorpsList.reset(donorCorps);”这将触发您的重置,并更新视图而不是重新初始化它。在第一次需要时初始化 app.donorCorpsList,如果它已经存在,只需更新它 :) - 希望这会有所帮助!
  • 最后 - 在视图初始化中保留范围:“this.collection.bind('reset', this.render);”应该是“this.collection.bind('reset', this.render, this);” - 如果不是“this.render”中的“this”,则指的是集合,而不是视图。
  • 阿门 reset/不要重新创建!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
相关资源
最近更新 更多