【发布时间】:2012-03-09 10:10:36
【问题描述】:
我有三种不同的方式来初始化和渲染一个视图及其子视图,每一种都有不同的问题。我很想知道是否有更好的方法可以解决所有问题:
场景一:
在父级的初始化函数中初始化子级。这样一来,并不是所有东西都卡在渲染中,从而减少了渲染阻塞。
initialize : function () {
//parent init stuff
this.child = new Child();
},
render : function () {
this.$el.html(this.template());
this.child.render().appendTo(this.$('.container-placeholder');
}
问题:
最大的问题是第二次在父节点上调用渲染会移除所有子节点的事件绑定。 (这是因为 jQuery 的
$.html()是如何工作的。)这可以通过调用this.child.delegateEvents().render().appendTo(this.$el);来缓解,但是第一种,也是最常见的情况,你做了更多不必要的工作。通过附加子级,您可以强制渲染函数了解父级 DOM 结构,以便获得所需的排序。这意味着更改模板可能需要更新视图的渲染功能。
场景二:
仍然在父级的initialize() 中初始化子级,但不是追加,而是使用setElement().delegateEvents() 将子级设置为父级模板中的一个元素。
initialize : function () {
//parent init stuff
this.child = new Child();
},
render : function () {
this.$el.html(this.template());
this.child.setElement(this.$('.placeholder-element')).delegateEvents().render();
}
问题:
- 这使得
delegateEvents()现在是必需的,这与它仅在第一种情况下的后续调用中是必需的相比略有负面。
场景三:
改为在父级的render() 方法中初始化子级。
initialize : function () {
//parent init stuff
},
render : function () {
this.$el.html(this.template());
this.child = new Child();
this.child.appendTo($.('.container-placeholder').render();
}
问题:
这意味着渲染函数现在也必须与所有初始化逻辑绑定在一起。
如果我编辑其中一个子视图的状态,然后在父视图上调用渲染,则会创建一个全新的子视图,并且其所有当前状态都将丢失。这似乎也可能导致内存泄漏。
真的很想得到你的家伙对此的看法。你会使用哪种场景?还是有第四种神奇的方法可以解决所有这些问题?
您是否曾经跟踪过视图的渲染状态?说renderedBefore 标志?看起来真的很笨拙。
【问题讨论】:
-
我通常不会在父视图上对子视图的引用进行排序,因为大多数通信都是通过模型/集合以及由这些更改触发的事件发生的。虽然第三种情况最接近我大部分时间使用的情况。案例 1 有意义的地方。此外,大多数时候您不应该重新渲染整个视图,而是重新渲染已更改的部分
-
当然,我肯定尽可能只渲染更改的部分,但即便如此,我认为渲染功能应该是可用的并且无论如何都是非破坏性的。您如何处理没有对父项中子项的引用?
-
通常我会监听与子视图关联的模型上的事件——如果我想做一些更自定义的事情,那么我会将事件绑定到子视图。如果需要这种“通信”,那么我通常会创建辅助方法来创建绑定事件等的子视图。
-
有关更高级别的相关讨论,请参阅:stackoverflow.com/questions/10077185/…。
-
场景二,为什么一定要在
setElement()之后调用delegateEvents()?根据文档:“......并将视图的委托事件从旧元素移动到新元素”,setElement方法本身应该处理事件重新委托。