2012-04-14 62 views
5

在網頁上我的項目(比如,產品卡,每個包含圖片和文字)的相當大名單 - 其中約1000。我想在客戶端過濾這個列表(只顯示那些未被過濾掉的項目),但是存在渲染性能問題。我申請一個非常狹窄的濾波器和10-20項仍然存在,則取消它(因此所有的項目都必須再次顯示),以及瀏覽器(Chrome很不錯的機器上)的一兩秒鐘掛斷。如何使用JavaScript最佳地呈現大量的DOM元素?

使用下列程序我重新渲染列表:

for (var i = 0, l = this.entries.length; i < l; i++) { 
    $(this.cls_prefix + this.entries[i].id).css("display", this.entries[i].id in dict ? "block" : "none") 
} 

字典是允許的項目IDS

這個功能本身運行瞬間的哈希值,它的渲染掛斷。有沒有比改變DOM元素的「顯示」屬性更好的重新渲染方法?

感謝您提前給出答案。

+1

你很驚訝重新渲染1000個元素需要1-2秒?因爲我懷疑在任何時候都有1000個元素都可見,所以也許你應該處理可見的項目,然後在後臺工作以使其餘部分可用(每次使用setTimeout()每次執行50次以保持瀏覽器活躍)。或者,也許你應該只有在由於滾動而變得可見的時候纔會放棄。它也不會幫助您運行1000個單獨的選擇器操作,每個操作都必須搜索整個DOM。 – jfriend00 2012-04-14 05:49:11

+0

給我們一個jsFiddle,我相信我們可以將切換性能提高10倍。代碼中有很多多汁的脂肪。 – jfriend00 2012-04-14 05:52:02

回答

4

爲什麼負荷1000個項目?首先你應該考慮像分頁。每頁顯示約30項。這樣,你不會加載太多。

那麼如果你真的成「圈了很多的項目」,可以考慮使用超時。 here's a demo我曾經說過循環的後果。它會阻止用戶界面,並會導致瀏覽器滯後,特別是在長循環中。但是在使用計時器時,您需要延遲每次迭代,讓瀏覽器稍後呼吸一下,然後在下一次迭代開始前執行其他操作。

還有一點要注意的是,你應該避免repaints and reflows,這意味着避免走動元素和多變的款式,當它沒有必要頻繁。另外,另一個技巧是從DOM中刪除實際上不可見的節點。如果您不需要顯示某些內容,請將其刪除。爲什麼浪費了記憶,把實際上沒有看到的東西?

+1

感謝「迴流」技巧 - 即使對於像我這樣的新手,也不知道這款漂亮瀏覽器的機器是不可原諒的。我從DOM中刪除了列表的容器,更改了元素的顯示屬性,然後將容器返回到了DOM。瞧,沒有迴流 - 沒有掛機! – 2012-04-14 06:13:16

-3

多德 - 處理「大量的DOM元素的」最好的辦法就是不這樣做在客戶端上,和/或者不使用JavaScript,如果你能避免它。

如果沒有更好的解決方案(並且我確定可能有!),那麼至少將您的工作分區劃分到您實際需要顯示的那一刻(而不是整個,大的,honkin'enchilada !)

+3

我低估了你的答案,因爲在客戶端/使用JavaScript處理大量DOM元素沒有任何不妥之處。平均計算機可以在一秒鐘內處理涉及數萬(如果不是更多)元素的DOM更新,前提是您儘量減少算法的複雜性,重排等。實際上,這通常比往返服務器,特別是因爲客戶端仍然會用服務器提供的任何HTML來更新DOM。問題不在JavaScript中,而在於它的使用方式。 – 2014-10-30 10:20:25

+1

2014年,客戶端渲染說「不要使用Javascript」非常差。特別是當我們有谷歌,Mozilla,微軟等公司每年投入數百萬美元時,爲最終用戶提供更快,更好和免費的WEB。也許這就是爲什麼最新的交易應用程序,雲解決方案,音樂播放器,CAD和圖形應用程序,大型商店(您的名字)所需要的只是一個可以免費下載的瀏覽器。 – Martin 2015-10-16 10:03:11

0

您可以使用setTimeout技巧從主線程卸載循環調用並避免客戶端凍結。我懷疑,總處理 - 從開始到結束 - 將持續的時間是相同的,但至少這種方式仍然可以使用的接口,其結果是更好的用戶體驗:

for (var i = 0, l = this.entries.length; i < l; i++) { 
    setTimeout(function(){ 
    $(this.cls_prefix + this.entries[i].id).css("display", this.entries[i].id in dict ? "block" : "none") 
    }, 0); 
}