2013-05-07 16 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();爲一個大塊。爲我工作得很好。 這很愚蠢,但這是真的。

相關問題