骨干视图嵌套

我在圈子里跑来跑去,似乎在我当前的应用程序实现backbone.js时遗漏了一些东西。 问题是我有一个主AppView,它初始化页面的各种子视图(图形,信息表等)。 我的愿望是能够根据导航时传递的参数标志来更改页面的布局。

我遇到的情况是,子视图引用了在呈现模板后将存在的dom元素,在主AppView初始化过程中无法访问这些元素。 所以主要的问题是如何确保每个事件绑定过程都有适当的dom元素才能正确设置?

如果我在LayoutView中有一个绑定到模型更改的事件,则使用以下代码,将呈现布局,但后续视图无法正确呈现。 我摆弄的一些东西是将所有视图’.el’值设置为html结构中的静态元素。 这会使渲染发生,尽管这似乎脱离了利用’.el’提供的良好作用域能力。

示例代码:

//Wrapped in jquery.ready() function... //View Code GraphView = Backbone.View.extend({ // init, model bind, template, supporting functions}); TableView = Backbone.View.extend({ // init, model bind, template, supporting functions}); LayoutView = Backbone.view.extend({ initialize: function() { this.model.bind('change:version', this.render, this); }, templateA = _.template($('#main-template').html()), templateB = _.template($('#secondary-template').html()), render: function() { if ('main' == this.model.get('version')) { this.el.html(this.templateA()); } else { this.el.html(this.templateB()); } }, }); MainView = Backbone.View.extend({ initialize: function() { this.layoutView = new LayoutView({ el: $('#layoutContainer'), model: layout, }); this.graphView = new GraphView({ el: $('.graphContainer'), model: graph }); this.tableView = new TableView({ el: $('#dataTableContainer', model: dataSet }); }, }); // Model Code Layout = Backbone.Model.extend({ defaults: { version: 'main', }, }); Graph = Backbone.Model.extend({}); dataSet = Backbone.Model.extend({}); // Router code... // Fire off the app AppView = new MainView($('#appContainer')); // Create route, start up backbone history 

HTML:为简单起见,我只重新排列了两个布局之间的div。

       
Some other stuff to identify that it's the main template
Rock on layout version two!

欣赏你们任何人可能拥有的洞察力/输入。 谢谢!

您的示例中有很多缺少的代码,但如果我理解正确,则问题是您尝试渲染依赖于LayoutView生成的HTML的LayoutView ,但是在更新模型时,将异步选择布局,所以LayoutView尚未渲染。

有(与几乎所有与Backbone相关的)多种方法,但总的来说:

  • 如果我有依赖于渲染“父”视图的视图,我将负责在父视图中实例化和渲染这些视图 – 在本例中为LayoutView ,而不是MainView

  • 如果父异步渲染,则需要在回调中执行该实例化 – 这里是LayoutView.render()方法。

所以我可能会像这样构造代码:

 LayoutView = Backbone.view.extend({ initialize: function() { this.model.bind('change:version', this.render, this); // you probably want to call this.model.fetch() here, right? }, templateA: _.template($('#main-template').html()), templateB: _.template($('#secondary-template').html()), render: function() { if ('main' == this.model.get('version')) { this.el.html(this.templateA()); } else { this.el.html(this.templateB()); } // now instantiate and render subviews this.graphView = new GraphView({ // note that I'm using this.$ to help scope the element el: this.$('.graphContainer'), model: graph }); this.tableView = new TableView({ el: this.$('.dataTableContainer'), model: dataSet }); // you probably need to call graphView.render() // and tableView.render(), unless you do that // in their initialize() functions }, }); 

请注意,您不必在实例化时传入el – 您可以在initialize()实例subview.render()视图,并在subview.render()设置el属性。 您甚至可以像在现在一样在MainView.initialize()实例化,并将视图传递给LayoutView以异步呈现。 但我认为上述方法可能更清晰。