我有一个嵌套 View 设置,它可以深入我的应用程序。我可以想到多种方法来初始化、渲染和附加 subview ,但我想知道常见的做法是什么。
这是我想到的几个:
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 顺序。 View 在早期就已初始化,因此在渲染函数中没有那么多事情要同时完成。
缺点:您被迫重新委托(delegate)事件(),这可能代价高昂?父 View 的渲染函数被所有需要发生的 subview 渲染弄得一团糟?您无法设置元素的 tagName
,因此模板需要维护正确的 tagName。
另一种方式:
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);
}
优点:您不必重新委派事件。您不需要仅包含空占位符的模板,并且您的标签名称将返回由 View 定义。
缺点:您现在必须确保以正确的顺序附加内容。父 View 的渲染仍然被 subview 渲染弄得一团糟。
使用 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();
}
优点: subview 逻辑现在与 View 的 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
中实例化 subview ? - 在
render
或onRender
中执行所有 subview 渲染逻辑? - 使用
setElement
还是append/appendTo
?
最佳答案
我通常看到/使用过几种不同的解决方案:
解决方案一
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();
}
});
这与您的第一个示例类似,但有一些变化:
- 附加子元素的顺序很重要
- 外部 View 不包含要在内部 View 上设置的 html 元素(意味着您仍然可以在内部 View 中指定 tagName)
render()
在内部 View 的元素被放入 DOM 之后调用,如果您的内部 View 的render()
方法正在放置/调整自身大小,这将很有帮助基于其他元素的位置/大小在页面上(根据我的经验,这是一个常见的用例)
方案二
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:
- 我的很多观点都依赖于已经在 DOM 中的
render()
方法 - 当重新渲染外部 View 时,不必重新初始化 View ,重新初始化可能会导致内存泄漏,还会导致现有绑定(bind)出现异常问题
请记住,如果每次调用 render()
时都初始化一个 new View()
,则该初始化将调用 delegateEvents()
无论如何。因此,正如您所表达的那样,这不一定是“骗局”。
关于javascript - 如何在 Backbone.js 中呈现和附加 subview ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9271507/