這篇文章主要講了CSS對背景圖片渲染效率的一些經驗和研究,在poluoluo.com中,還有著類似CSS效率的相關文章。
樹型結構豎線用樣式表(背景圖)來實現,樣式表背景圖片只需要加載一次,而現在這個模式(用多個<img>)圖片雖然有緩存機制,但還是有可以每張小圖片都請求一次服務器的,所以我想用樣式表來實現有多麼的好呀,代碼又精簡,結構又清晰,效果又酷,但是結果我將近一個星期的測試,我這種設想徹底失敗,原因就是樣式表的渲染效率太差。新的構想沒能實現,心情有些沮喪,但我想也應該讓大家分享一下這個測試成果。
這裡我再解釋一下樹型裡的豎線,樹的左邊都有 ┌ ├ └ │ 這些豎線圖表示樹層次,我的1.0版裡是用一張張的小圖片堆積起來的,而這種使用樣式表的是用<div class="l2"></div> (l是字母L)這種代碼來實現的,樣式表負責填充背景圖。
#www_poluoluo_com .l0{background:url(line0.gif) no-repeat center}
#www_poluoluo_com .l1{background:url(line1.gif) no-repeat center}
#www_poluoluo_com .l2{background:url(line2.gif) no-repeat center}
#www_poluoluo_com .l3{background:url(line3.gif) no-repeat center}
#www_poluoluo_com .l4{background:url(line4.gif) no-repeat center}
#www_poluoluo_com .ll{background:url(line5.gif) no-repeat center}
#www_poluoluo_com .pm0{background:url(plus0.gif) no-repeat center}
#www_poluoluo_com .pm1{background:url(plus1.gif) no-repeat center}
#www_poluoluo_com .pm2{background:url(plus2.gif) no-repeat center}
#www_poluoluo_com .pm3{background:url(plus3.gif) no-repeat center}
#www_poluoluo_com .expand .pm0{background:url(minus0.gif) no-repeat center}
#www_poluoluo_com .expand .pm1{background:url(minus1.gif) no-repeat center}
#www_poluoluo_com .expand .pm2{background:url(minus2.gif) no-repeat center}
#www_poluoluo_com .expand .pm3{background:url(minus3.gif) no-repeat center}
上面這段CSS是我在腳本裡動態生成的一段樣式的片段,我把它貼上來,有助於後面的講解。運用樣式表之後,果真精簡了許多,每個節點的生成也夠快,但我發現,當我的樹節點量達到,比如說300-500個節點之後,節點生成的效率沒有影響什麼,但每個節點的展開/收縮很慢很慢,需要幾秒鐘以上甚至10秒,且這個期間的CPU占用率是100%。說明一下,樹型的展開/收縮是設置父節點的 style.display = none|block 來實現的。我的電腦配置是:AMD2800+ 1GDDR400內存,配置不太差的。
我首先的反應是:是不是用了太多的<table>影響了效率?因為我每一個節點都用了一個<table>,但是我把<table>換成了<div>、<span>等,效率沒有什麼改善,說明這個CPU占用率100%的問題不是HTML標簽的問題,那麼剩下來的問題就是這裡使用了樣式表。
以一個500節點的量來說吧,1.0裡左邊大概要堆積2000個左右的小圖片。這種情況在浏覽器端設置本地不緩存的時候會存在很大的問題,要加載這些多的小圖片需要消耗不少的時間和服務器資源,所以我才會有這種新的用樣式表來解決的想法,現在換成樣式表法,也就是大概有2000個地方需要用樣式表來渲染出背景圖。我測試了各種情況,再對比1.0版的代碼得出的結論是:CPU的點用率如此之高,唯一的原因也就只有這種渲染的耗時了。驗證也非常簡單,我把上面的樣式表的左邊 #www_poluoluo_com 這部分去掉,也就是去掉樣式表的依托關系,測試的結果發現效率改善了很多,但耗時依然是可觀的,有3-5秒之多。
另外我換了不同的浏覽器,測試的結果也不太一樣,在IE裡最為惡心,比如說我在某個節點有500子節點,我將它收起(CPU100%,等待3-5秒),也就是display="none",這時候若我去收起這個節點的父節點(這個節點沒有其它的同級節點,即它的父節點只有它這麼一個子節點),照理說只有一個節點,收起應該是即時的事,但結果不然,結果又是3-5秒的CPU100%,這個讓我狂郁悶,也就是說即使HTML對象被display="none"隱藏掉了,但是對它的父級進行任何操作的時候,IE會對這些被隱藏的對象用樣式表重新渲染一遍,真是搞不懂IE的開發者當初是怎麼想的。
我又到FIREFOX裡測試了一下,在收起的時候(display=none)是瞬間的,可以肯定,FF對待被隱藏的對象不會再消耗精力。當然展開的時候所有的浏覽器都一樣:3-5秒的CPU100%,不過FF稍微要快些。
通過上面的這些現象我得出這麼一個結論:樣式表在動態渲染的時候效率並不高;在父容器發現狀態變化的時候會引起它的所以子孫對象的樣式表重新渲染;FireFox 對待被display=none隱藏的對象不會重新渲染而IE會。
那麼這種樣式表的渲染效率問題以前為什麼一直沒有被發現呢?嘿嘿,大家做網頁的時候難得會做到這種極端的時候,一個頁面裡有幾千個需要樣式表渲染背景圖。通常也就幾個地方或者幾十個地方了,所以感覺不出來渲染的效率,也感覺不出這方面在不同的浏覽器之間的差別。但是在做樹這些的控件的時候必定會碰到各種極端的問題,比如大數據量的數組,生成的HTML對象的多少等等,象這種渲染的效率差別也只是我在寫JS腳本時碰到的問題之一而已。今天我把這個測試結果共享出來是希望對大家以後寫程序的時候有所借薦,在做設計的時候有所考慮。