我的MzTreeView1.0樹控制項發布至今,得到了不少意見反饋,很多網友給了我很多的中肯的建議,也指出了這個控制項裡的諸多BUG和不足之處,所以我準備寫一個新版本的樹,將大家的建議都整合進來實現。這幾天我就一直在寫新版的樹,樹控制項最重要的是效率,特別是大節點量的時候,效率稍微差點的模式就會拖垮瀏覽器,所以新版的樹我首要的還是提高效率,比如增加非同步資料載入的支援等,另外我還有一個設想,就是樹的樹型結構豎線用樣式表(背景圖)來實現,樣式表背景圖片只需要載入一次,而現在這個模式(用多個)圖片雖然有緩衝機制,但還是有可以每張小圖片都請求一次伺服器的,所以我想用樣式表來實現有多麼的好呀,代碼又精簡,結構又清晰,效果又酷,但是結果我將近一個星期的測試,我這種設想徹底失敗,原因就是樣式表的渲染效率太差。新的構想沒能實現,心情有些沮喪,但我想也應該讓大家分享一下這個測試成果。
這裡我再解釋一下樹型裡的豎線,樹的左邊都有 ┌ ├ └ │ 這些豎線圖表示樹層次,我的1.0版裡是用一張張的小圖片堆積起來的,而這種使用樣式表的是用 這種代碼來實現的,樣式表負責填充背景圖。
#mtvroot div td{width:20px;height:20px;}
#mtvroot .l0{background:url(line0.gif) no-repeat center}
#mtvroot .l1{background:url(line1.gif) no-repeat center}
#mtvroot .l2{background:url(line2.gif) no-repeat center}
#mtvroot .l3{background:url(line3.gif) no-repeat center}
#mtvroot .l4{background:url(line4.gif) no-repeat center}
#mtvroot .ll{background:url(line5.gif) no-repeat center}
#mtvroot .pm0{background:url(plus0.gif) no-repeat center}
#mtvroot .pm1{background:url(plus1.gif) no-repeat center}
#mtvroot .pm2{background:url(plus2.gif) no-repeat center}
#mtvroot .pm3{background:url(plus3.gif) no-repeat center}
#mtvroot .expand .pm0{background:url(minus0.gif) no-repeat center}
#mtvroot .expand .pm1{background:url(minus1.gif) no-repeat center}
#mtvroot .expand .pm2{background:url(minus2.gif) no-repeat center}
#mtvroot .expand .pm3{background:url(minus3.gif) no-repeat center}
上面這段CSS是我在指令碼裡動態產生的一段樣式的片段,我把它貼上來,有助於後面的講解。運用樣式表之後,果真精簡了許多,每個節點的產生也夠快,但我發現,當我的樹節點量達到,比如說300-500個節點之後,節點產生的效率沒有影響什麼,但每個節點的展開/收縮很慢很慢,需要幾秒鐘以上甚至10秒,且這個期間的CPU佔用率是100%。說明一下,樹型的展開/收縮是設定父節點的 style.display = none|block 來實現的。我的電腦配置是:AMD2800+ 1GDDR400記憶體,配置不太差的。
我首先的反應是:是不是用了太多的
等,效率沒有什麼改善,說明這個CPU佔用率100%的問題不是HTML標籤的問題,那麼剩下來的問題就是這裡使用了樣式表。
以一個500節點的量來說吧,1.0裡左邊大概要堆積2000個左右的小圖片。這種情況在瀏覽器端設定本地不緩衝的時候會存在很大的問題,要載入這些多的小圖片需要消耗不少的時間和伺服器資源,所以我才會有這種新的用樣式表來解決的想法,現在換成樣式表法,也就是大概有2000個地方需要用樣式表來渲染出背景圖。我測試了各種情況,再對比1.0版的代碼得出的結論是:CPU的點用率如此之高,唯一的原因也就只有這種渲染的耗時了。驗證也非常簡單,我把上面的樣式表的左邊 #mtvroot 這部分去掉,也就是去掉樣式表的依託關係,測試的結果發現效率改善了很多,但耗時依然是可觀的,有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指令碼時碰到的問題之一而已。今天我把這個測試結果共用出來是希望對大家以後寫程式的時候有所借薦,在做設計的時候有所考慮。
最後多謝大家對我寫的控制項的肯定與支援,謝謝了!