我的MzTreeView1.0樹控件發布至今,得到了不少意見反饋,很多網友給了我很多的中肯的建議,也指出了這個控件裡的諸多BUG和不足之處,所以我准備寫一個新版本的樹,將大家的建議都整合進來實現。這幾天我就一直在寫新版的樹,樹控件最重要的是效率,特別是大節點量的時候,效率稍微差點的模式就會拖垮浏覽器,所以新版的樹我首要的還是提高效率,比如增加異步數據加載的支持等,另外我還有一個設想,就是樹的樹型結構豎線用樣式表(背景圖)來實現,樣式表背景圖片只需要加載一次,而現在這個模式(用多個<img>)圖片雖然有緩存機制,但還是有可以每張小圖片都請求一次服務器的,所以我想用樣式表來實現有多麼的好呀,代碼又精簡,結構又清晰,效果又酷,但是結果我將近一個星期的測試,我這種設想徹底失敗,原因就是樣式表的渲染效率太差。新的構想沒能實現,心情有些沮喪,但我想也應該讓大家分享一下這個測試成果。
這裡我再解釋一下樹型裡的豎線,樹的左邊都有 ┌ ├ └ │ 這些豎線圖表示樹層次,我的1.0版裡是用一張張的小圖片堆積起來的,而這種使用樣式表的是用<div class="l2"></div> 這種代碼來實現的,樣式表負責填充背景圖。
#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內存,配置不太差的。
我首先的反應是:是不是用了太多的<table>影響了效率?因為我每一個節點都用了一個<table>,但是我把<table>換成了<div>、<span>等,效率沒有什麼改善,說明這個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秒