BackboneJS view rendering delay, on iPhone 4s (iOS 8), 2015
我正在使用BackboneJS(jQuery Underscore)制作一个单页的Web应用程序,并且正在各种浏览器和各种设备上对此进行测试。最终它将成为Phonegap应用。
效果很好,但是在iPhone 4s(iOS 8)上,我所有的路线渲染速度都很慢(大约一秒钟)。我尚未解决300毫秒的点击延迟,但稍后会担心。我的一条路线使问题变得更加严重,该路线的视图数量特别多(?30),并且可能需要5秒钟才能在此设备上进行渲染。
这是我的路线示例:
1 2 3 4 | 'some_route': function(){ if(APP.controller) APP.controller.destruct(); APP.controller = new SomeController(); }, |
所有视图都在控制器实例化期间实例化并呈现(并且应分别更新DOM)。这是一个视图渲染函数的示例,该路由加载时会调用许多视图:
1 2 3 4 | render: function() { var modelData = this.model.toJSON(); this.$el.html(this.template(modelData)); }, |
有趣的是,如果我在路由的控制器实例下添加了警报,则它会在UI更改出现之前(3-4秒之前)发生。并且,所有UI更改都将立即显示。鉴于JavaScript是单线程的,这没有多大意义。除非jQuery以某种方式异步处理.html()调用,否则浏览器将延迟应用于可视DOM更新...
我在模板的末尾附加了一个时间戳(因此每个视图的末尾都带有时间戳),以查看执行每个视图需要花费多长时间。第一个和最后一个之间的差异仅为0.03s,但是浏览器仍然需要将近5秒钟才能将更改实际呈现到屏幕上(在此期间,它没有响应)。
我仔细研究了render函数,发现执行以下操作可以大大提高性能,但是并不能解决我的问题:
1 2 3 4 5 | render: function() { var modelData = this.model.toJSON(); this.template(modelData); //call anyway to gauge performance impact this.$el.html(''); //call anyway, but with nothing }, |
这可能是内存问题吗?与Backbone 导航(URL更改)有关吗?还有其他人遇到吗?我已经四处搜寻,但我真的没有运气找到任何遇到相同问题的人。
更新
为视图元素简单地添加
您有多少次观看?如果在实例化控制器时呈现了所有视图(这可能是一个缓慢的功能),请尝试添加类似这样的内容以检查花费的时间
1 2 3 4 | var timeStart = performance.now(); APP.controller = new SomeController(); var timeEnd = performance.now(); console.log('time ' + (timeEnd - timeStart) + ' ms'); |
的确JavaScript是单线程的,但是您必须记住浏览器如何执行所有任务,请查看该问题的第二个答案为什么setTimeout(fn,0)有时有用?。
我找到了两种解决方案。
首先,页面上有沉重的背景图像。注释掉这些CSS,并为麻烦的路径删除正在加载的视图的CSS,将延迟减少了一半。减少应用程序正在使用的资源(甚至是背景图像)似乎可以直接减少延迟。
因此,一种解决方案是优化图像和CSS。使用的内存越少越好。
其次,我发现可以在路线转换期间显示加载屏幕,从而大大降低了UX的影响。我正在使用这样的东西:
1 2 3 4 5 6 7 8 | 'some_route': function(){ $('#overlay').show(); setTimeout(function(){ if(APP.controller) APP.controller.destruct(); APP.controller = new SomeController(); $('#overlay').hide(); },30); }, |
这样,浏览器有时间在视图渲染受到冲击之前显示加载叠加层-这似乎是造成延迟的原因-最后它会删除叠加层。
当然,如果在浏览器完成VISUALLY呈现更改后(不仅仅是在javascript执行结束之后)发生了某个事件,可以用一种更好的方法来完成。