重用主干视图
Reusing Backbone Views
我正在编写一个用户以线性方式移动的 Backbone 应用程序。该应用程序的工作方式类似于电视节目,旁白引导用户从一个场景到另一个场景的剧集。
为了实现这一目标,我有一个父剧集视图,负责在正确的时间加载正确的场景视图。到目前为止,我对此功能的运作方式感到满意。
我需要添加用户在闲暇时从一个场景跳到另一个场景的功能。可能在应用程序的整个生命周期中多次查看同一场景。我的问题是,我是否应该在每次加载同一场景时创建一个新的场景视图,或者我是否应该创建一个场景实例,然后在用户第二次、第三次或第四次加载它时重新使用它。
下面的示例显示了到目前为止我如何重用这些场景。
loadSceneView: function()
{
var sceneIndex = this.model.getCurrentIndex();
if(this.scenes[sceneIndex])
{
this.scenes[sceneIndex].render();
console.log('Scene: ' + sceneIndex + ' already loaded. Reusing');
}
else
{
console.log('Loading Scene: ' + sceneIndex);
switch(sceneIndex)
{
case 0:
this.scenes[sceneIndex] = new cith.Views.Scene1();
break;
case 1:
this.scenes[sceneIndex] = new cith.Views.Scene2();
break;
case 2:
this.scenes[sceneIndex] = new cith.Views.Scene3();
break;
}
}
this.currentScene = this.scenes[sceneIndex];
this.listenTo(this.currentScene, 'scene:ended', this.goToNextScene);
$('#scene').html(this.currentScene.el);
}
基本上,如果场景数组具有与当前sceneIndex
匹配的索引,则只需将该视图加载到 dom 中即可。 否则,请创建它,在场景数组中保留对它的引用并将其加载到 DOM 中。
谁能帮我确定这种方法的优缺点?具体来说,我关心的是尽可能的最佳性能,以及避免内存泄漏,因为保留对这些对象的引用的副作用是我(或可能不会)再次使用。
谢谢。
除非您正在构建一个真正资源密集型的应用程序,否则这可能是过早的优化。 我会使用最简单的方法,如果性能证明是一个问题,我会稍后优化代码。
除此之外,可能没有绝对正确的答案。 您需要权衡几个因素:
- (重新)构建场景所需的时间。
- 非活动场景将使用的内存量
- 场景的使用频率
- 总共有多少场景
如果构建场景的速度足够快,以至于用户不会注意到,并且不涉及下载或加载额外的资源,那么每次都重新渲染视图可能没问题。 但是,如果渲染需要一段时间,那么也许您应该考虑保留视图。 同样,我肯定会保留一个可能重复使用的资源缓存。
另一方面,我猜你的视图将使用非常少量的内存(特别是与现在大多数机器和手机的RAM相比),所以将它们保存在内存中可能不是什么大问题(除非你认为你最终会有数千个内存仍在内存中 - 实际上取决于你认为用户将在单个会话中与之交互的视图数量)
如果您真的担心使用太多内存,那么您可以随时缓存一些视图而不是所有视图 - 要么通过它们被重用的可能性,要么通过某种"最新视图"方案,其中最近的 20 个(或其他)视图存储在内存中,其余的在需要时构建。 然而,这有点复杂,而且很可能矫枉过正。
实际上,您显然知道它但需要确认,您的建议是应该做什么,视图应该只创建一次,然后在需要时渲染,至于内存需求它仅取决于您拥有的场景总数,但是,我仍然无法想象浏览器会因为耗尽内存而放弃的情况, 所以,以我的拙见,你的工作非常好,这就是我会做的。
是什么阻止您预先创建所有视图并在运行时从缓存数组中获取它们?你的观点真的是资源密集型的吗?如果是这样,缓存是有意义的,你的上述方法很好。如果没有,我要么动态创建它们(无缓存/重用),要么预先创建所有这些(在数组中缓存引用)并在运行时获取它们。如果您担心性能/内存泄漏使用情况,可以使用如下所示的内容:
var dispatcher = _.clone(Backbone.Events); //Event-bus for all the views to talk to each other
/*
* Create a BaseView for all classes to inherit from. "Intercept" Backbone's constructor
* by providing a hook for any custom initialization that needs to be done across views.
*/
//reference to Backbone.View's constructor
var ctor = Backbone.View;
//extend Backbone.View
var BaseView = Backbone.View.extend({
//override the constructor property
constructor: function(options){
//call Backbone.View's constructor (ctor) and just proxy the arguments to it
ctor.apply(this, arguments);
//perform initialization here
dispatcher.on('close',this.close, this);
},
//Adding a custom close method inheritable by all 'children' of BaseView.
close: function(){
//if an onClose 'handler' is defined by the class execute it - for any custom 'close' logic to be called
if(this.onClose)
this.onClose();
this.off();
this.undelegateEvents();
this.remove();
}
});
您可以使用 close()
方法为所有视图创建一个"基类",该方法将视图与相应的模型和事件解除绑定,并将自身从视图/DOM 中删除。这可以与您的缓存策略结合使用,或者如果事情趋向于变化,您根本不需要缓存任何内容(同时由其他用户并且您不想实现轮询或尚未实现服务器端推送)。如果/当我知道我将有太多可能导致内存使用/泄漏从而降低性能的对象时,我会使用此策略。
希望这对:)有所帮助
- 如何使用javascript从主svg对象动态创建svg视图框
- 正在使用$location.path(.)路由ng视图
- angular.js没有'无法在PhoneGap中处理视图标记
- 如何包含特定于每个视图angularjs的javascript文件
- 通过在Dojo mobile ViewController.openExternalView中动态更改打开同一外部视图的
- Kendo:我该如何在树视图中创建一个递归的hieiarchy
- Ajax Live搜索发布到Laravel视图
- backbone.js无法渲染视图
- 根据某些条件在视图之间切换
- ng视图外的链接重定向到ng视图内的页面
- 如何在Jquery中发布后将值从视图返回到控制器
- 将日期时间作为 JSON 发送将无法在我的视图中正确显示
- 使用Scala Play Framework视图中的键检索映射值
- FF视图源|脚本高亮显示为红色
- 如何使bxslider仅在移动视图中处于活动状态
- 为什么不't我的变量在我的控制器中填充后在我的视图中呈现
- 在不破坏未定义函数的情况下,对多个视图使用单个js文件
- 在Rails中更新Div,而不更改更新请求后的视图
- 如何在Ionic Android中将Javascript注入到web视图中
- 如何在视图模型contet更新更新上调用Jquery函数