2013-05-07 57 views
35

我有一个使用Knockout.js 2.2.1显示信息流从服务器(使用socket.io,但我不认为重要)的单页网络应用程序。此应用程序还包含一个大型数据表,该数据表是使用Knockout的foreach绑定从JSON对象创建的。 (表格很大,但不是很大:20列,200行左右)为什么Chrome在隐藏大型Knockout元素时使用更多的CPU?

由于表格很大,用户可以通过点击按钮来打开/关闭表格。数据<table>被放置在<div>元素中,我可以使用jQuery的.hide().show()方法(基本上通过设置和清除<div>上的CSS display: none)来隐藏/显示数据。

所有这些功能的作品。但是,我注意到在'关闭'(隐藏)大数据表后,Chrome的CPU使用率跳转 - 如果Knockout生成的表足够大,一直到100%。更有趣的是,这个只有发生在用户点击包含表格的<div>元素内的某个地方时。当表被隐藏(并且CPU使用率高)时,单击页面上的其他位置将使CPU使用率恢复正常。该过程将随意重复。

另一个可能有用的注意事项:如果我停止从服务器传输数据,则不会发生此问题(或者,CPU使用率不明显)。在此页面上有一个Knockout视图模型,该模型管理来自服务器的流式数据以及从JSON对象创建此数据表。这两组数据在其他方面是完全分开的 - 没有任何更改的数据显示在表中,并且表中不包含事件绑定回视图模型。就好像Knockout模型的流数据更新正在导致数据表上的工作,即使没有流数据绑定到表。 它只有当这个表是而不是显示!

快速摘要:

  • 的Web应用程序使用淘汰赛加载页面时呈现一个大的数据表。
  • 此表在$(document).ready启动隐藏着.hide(),但使用.show()显示,点击一个按钮后,可再次隐藏
  • 如果鼠标点击的数据表中,在Chrome的CPU使用率会跳到表格被隐藏后,100%。
  • 单击页面上的其他任何内容都会使CPU使用恢复正常。

其他相关信息:

  • 的Chrome浏览器的JavaScript探查显示了CPU使用率过高,但它只是归类为(节目)的时间。
  • Windows上的IE10和Firefox 20都不显示此问题。

任何想法这里发生了什么,或有其他疑难解答的建议吗?

的jsfiddle:

这里举例:http://jsfiddle.net/CTYMv/6/

看看加载小提琴后CPU使用率,它应该是低的。点击“Show Table”,然后点击弹出的div内的某个地方(灰色背景)。然后点击“隐藏表” - CPU使用率将显着增加。然后点击其他任何地方(白色背景),CPU将恢复正常。

+1

你能提供一个小提琴吗? – C5H8NNaO4 2013-05-08 23:16:30

+0

其实是的。我认为模拟会有点困难,但设法得到一个很好的例子。 – potatoe 2013-05-09 18:23:45

+0

您的问题可能是由浏览器重排造成的?你检查过了吗? – 2013-05-09 19:02:51

回答

3

我想我们现在可以认为这是webkit引擎中的一个错误。此错误仅在使用css属性display:none;时才会显示。这是由于使用webkit的GPU如何渲染隐藏的元素?好了,我还是不知道......

SEE DEMO

这是我能想到的简单的解决方法,这不应该与任何其他的干扰代码:{如剔除可观察}

CSS: {添加指针事件由布兰登建议}

.hidden{opacity:0;pointer-events:none} //don't use display:none here 

JS:

//don't use hide/show jq methods as internally it set display none (fadeOut() methods too) 
$('#btn_show').click(function(){ 
    $('#bigdatadiv').removeClass('hidden'); 
}); 
$('#btn_hide').on('click',function(){  
    $('#bigdatadiv').addClass('hidden') 
}); 

我知道这只是一种解决方法,仍然没有回答你的问题:为什么会发生这种情况?

+1

你也想添加'pointer-events:none;'给隐藏的css类。 – Brandon 2013-05-17 15:32:15

+0

另外...当你用'window.getSelection()'在div上设置'display:none'时清除文本选择。removeAllRanges()似乎也可以工作:http://jsfiddle.net/bman654/jjkf9/3/ – Brandon 2013-05-17 15:33:07

+0

@Brandon Ya,pointer-events:none也可以添加。 window.getSelection()。removeAllRanges()是另一种可能的解决方法。 – 2013-05-17 15:41:03

0

Thankyou for this thread;你会认为这个bug在2年后会被修复。

window.getSelection()。removeAllRanges()为我解决了一些问题,并且最适合我的代码。

-2

只需使用window.getSelection().removeAllRanges() 之前.hide();为一个大块。为我工作得很好。 这很愚蠢,但这是真的。

相关问题