我正在乱跑,似乎在我当前的应用程序实现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。
<html>
<head>
<!-- include above js and backbone dependancies -->
</head>
<body>
<script type="text/template" id="main-template">
<div class="graphContainer"></div>
<div class="dataTableContainer"></div>
<div>Some other stuff to identify that it's the main template</div>
</script>
<script type="text/template" id="secondary-template">
<div class="dataTableContainer"></div>
<div>Rock on layout version two!</div>
<div class="graphContainer"></div>
</script>
<div id="appContainer">
<div id="nav">
<a href="#layout/main">See Layout One</a>
<a href="#layout/secondary">See Layout Two</a>
</div>
<div id="layoutContainer"></div>
</div>
</body>
</html>
欣赏任何人可能拥有的洞察力/输入。谢谢!
答案 0 :(得分:8)
您的示例中有很多缺少的代码,但如果我理解正确,则问题是您尝试呈现依赖于LayoutView
生成的HTML的视图,但是正在选择布局更新模型时异步,因此尚未呈现LayoutView
。
与(与几乎所有与Backbone相关的)方法有多种方法,但总的来说:
如果我有依赖于呈现“父”视图的视图,我将负责在父视图中实例化和呈现这些视图 - 在本例中为LayoutView
,而不是{ {1}}。
如果异步渲染父级,则需要在回调中执行该实例化 - 此处为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()
中设置el
属性。您甚至可以像现在一样在subview.render()
中实例化,并将视图传递给MainView.initialize()
以异步呈现。但我认为上述方法可能更清晰。