我有一个嵌套的视图设置,它可以深入到我的应用程序中。有一堆方法我可以想到初始化,渲染和附加子视图,但我想知道常见的做法是什么。
下面是我想到的几个:
initialize : function () {
this.subView1 = new Subview({options});
this.subView2 = new Subview({options});
},
render : function () {
this.$el.html(this.template());
this.subView1.setElement('.some-el').render();
this.subView2.setElement('.some-el').render();
}
的优点:你不必担心通过追加来维护正确的DOM顺序。视图是在早期初始化的,所以在渲染函数中没有那么多事情要一次完成。
缺点:您被迫重新委托costly (),这可能很昂贵?父视图的渲染函数被需要进行的所有子视图渲染弄得乱七八糟?您不能设置元素的tagName
,因此模板需要维护正确的tagNames。
另一种方式:
initialize : function () {
},
render : function () {
this.$el.empty();
this.subView1 = new Subview({options});
this.subView2 = new Subview({options});
this.$el.append(this.subView1.render().el, this.subView2.render().el);
}
优点:你不必重新委托事件。您不需要只包含空占位符的模板,并且您的tagName将重新由视图定义。
缺点:现在你必须确保以正确的顺序追加内容。父视图的渲染仍然受到子视图渲染的影响。
使用onRender
事件:
initialize : function () {
this.on('render', this.onRender);
this.subView1 = new Subview({options});
this.subView2 = new Subview({options});
},
render : function () {
this.$el.html(this.template);
//other stuff
return this.trigger('render');
},
onRender : function () {
this.subView1.setElement('.some-el').render();
this.subView2.setElement('.some-el').render();
}
优点:子视图逻辑现在从视图的render()
方法中分离出来。
使用onRender
事件:
initialize : function () {
this.on('render', this.onRender);
},
render : function () {
this.$el.html(this.template);
//other stuff
return this.trigger('render');
},
onRender : function () {
this.subView1 = new Subview();
this.subView2 = new Subview();
this.subView1.setElement('.some-el').render();
this.subView2.setElement('.some-el').render();
}
我在所有这些示例中混合和匹配了一堆不同的实践(很抱歉),但是您会保留或添加哪些实践呢?还有什么是你不会做的?
实践总结:
initialize
或render
render
中或onRender
setElement
或append/appendTo
中的所有子视图呈现逻辑
发布于 2012-06-23 00:20:48
我通常看到/使用了几种不同的解决方案:
解决方案1
var OuterView = Backbone.View.extend({
initialize: function() {
this.inner = new InnerView();
},
render: function() {
this.$el.html(template); // or this.$el.empty() if you have no template
this.$el.append(this.inner.$el);
this.inner.render();
}
});
var InnerView = Backbone.View.extend({
render: function() {
this.$el.html(template);
this.delegateEvents();
}
});
这与您的第一个示例类似,但有一些更改:
render()
中的tagName,如果内部视图的render()
方法根据其他元素的位置/大小在页面上放置自身/调整自身大小)会很有帮助
解决方案2
var OuterView = Backbone.View.extend({
initialize: function() {
this.render();
},
render: function() {
this.$el.html(template); // or this.$el.empty() if you have no template
this.inner = new InnerView();
this.$el.append(this.inner.$el);
}
});
var InnerView = Backbone.View.extend({
initialize: function() {
this.render();
},
render: function() {
this.$el.html(template);
}
});
解决方案2可能看起来更干净,但它在我的经验中造成了一些奇怪的事情,并对性能产生了负面影响。
我通常使用解决方案1,原因有几个:
render()
方法请记住,如果每次调用render()
时都要初始化new View()
,则该初始化无论如何都会调用delegateEvents()
。因此,正如您所表达的,这不一定是一个“骗局”。
发布于 2012-02-14 12:43:53
这是一个长期存在的问题,在我的经验中,这个问题并没有一个令人满意的答案。我和你一样沮丧,特别是因为尽管这种用例很常见,但指导太少了。也就是说,我通常会使用类似于你的第二个例子的东西。
首先,我会立即排除任何需要您重新委托事件的事情。Backbone的事件驱动视图模型是它最关键的组件之一,仅仅因为你的应用程序很重要就失去了这个功能,这会给任何程序员留下不好的印象。所以从第一点开始。
关于你的第三个例子,我认为它只是绕过了传统的渲染实践,并没有增加太多的意义。也许,如果您正在进行实际的事件触发(即,不是人为的"onRender
“事件),那么将这些事件绑定到render
本身可能是值得的。如果您发现render
变得笨拙和复杂,那么您的子视图太少了。
回到你的第二个例子,这可能是三害中较小的一个。下面是摘自的示例代码,可以在我的PDF版本的第42页找到:
...
render: function() {
$(this.el).html(this.template());
this.addAll();
return this;
},
addAll: function() {
this.collection.each(this.addOne);
},
addOne: function(model) {
view = new Views.Appointment({model: model});
view.render();
$(this.el).append(view.el);
model.bind('remove', view.remove);
}
这只是一个比您的第二个示例稍微复杂一点的设置:它们指定了一组函数addAll
和addOne
,用于完成繁琐的工作。我认为这种方法是可行的(我当然会使用它);但它仍然留下了奇怪的回味。(请原谅所有这些舌头比喻。)
关于以正确的顺序添加的观点:如果您严格地添加,当然,这是一个限制。但一定要考虑所有可能的模板方案。也许您实际上想要一个占位符元素(例如,一个空的div
或ul
),然后您可以replaceWith
一个包含相应子视图的新(DOM)元素。追加并不是唯一的解决方案,如果你那么关心它,你当然可以绕过排序问题,但如果它让你绊倒,我可以想象你有一个设计问题。请记住,子视图可以有子视图,如果合适的话,它们应该有子视图。这样,您就有了一个相当不错的树状结构:每个子视图按顺序添加其所有子视图,然后父视图添加另一个子视图,依此类推。
不幸的是,解决方案#2可能是您希望使用开箱即用主干的最好方案。如果你对第三方库感兴趣,我已经研究过的(但实际上还没有时间)是Backbone.LayoutManager,它似乎有一种更健康的添加子视图的方法。然而,即使是他们在类似的问题上也有recent debates。
发布于 2014-04-03 07:06:35
令人惊讶的是,这还没有被提及,但我会认真考虑使用Marionette。
它为主干应用程序增加了更多的结构,包括特定的视图类型(ListView
、ItemView
、Region
和Layout
),添加了适当的Controller
等等。
这里有the project on Github和一个很棒的guide by Addy Osmani in the book Backbone Fundamentals,可以帮助你入门。
https://stackoverflow.com/questions/9271507
复制相似问题