摘要: 此篇文章包括了一些在網頁設計中時常用到的腳本。我們可以清晰的體會到其中的執行速度。這將有助于提高您的動態網頁的速度。 導言: 自從有了IE4.0以后,我們所看到的網頁一天一天的栩栩如生。可以說IE4時代的到來,是我們的眼界更加的寬廣了。我們應用IE4,從中我們得到的好處是,可以在自己的個人站點上加入更多的圖片、動畫、網頁特效,以此來體現我們的個性。強大的DHTML技術使得網頁會有非同尋常的變化。甚至在某些時刻,運用這項技術可以我們可以模仿很多東西---比如說Windows的界面、Flash的動態效果---當然前提是您需要掌握這項技術。DHTML還有一個非常有意思的地方就是,通常同一種功能,它提供了不止一種的實現形式。換句話說也就是我們可以用不同的代碼來實現同樣的功能。但這就有執行效率的問題了,而這篇文章,我們討論的就是這個東西。 DHTML網頁中的變化:
一條最基本的更新動態網頁的方法改變你網頁上的內容。客戶端的腳本,您可以使用DHTML object model或者W3C document object model(DOM)來為網頁上添加新的元素。無論您何時改變動態網頁,瀏覽器總是首先來識別網頁內在的表示,然后會重新計算展現在客戶端的網頁的內容的具體的尺寸。如果您希望在網頁上新加入一塊新的內容,那么此時HTML語法分析器是需要被調用的,此時必然會帶來一部分多余的開銷。您可以使用insertAdjacentHTML和pasteHTML兩種方法,以及innerHTML和outerHTML兩種屬性來在網頁上添加新的內容文字。 | 方法一:改變HTML文字所使用的腳本,最好放在同一個腳本函數中。如果設計的時候一定要使用不同的腳本函數,比如當調用onmouseover和onmouseout這樣一類的事件的時候,使你的腳本在一處出現最好。 | 這里需要大家知道的是,每當頁面執行一個腳本函數,HTML編譯器總是要重新計算現有的文字的格式,以及各自在網頁中的位置。這樣您或許就清楚為什么要把腳本都寫在一個腳本函數中。(當然同樣我也不希望,您改變您現在調用很多函數的代碼書寫風格。) | 方法二:當需要改變文檔內容的時候,使用一個HTML的字符串型的變量來代替所有需要修改的內容,進行一次修改,而不是一次一次的來改變文檔的內容。如果不需要HTML的目錄,這時候可以考慮使用innerText屬性。 | 在下面的例子中,“慢”的例子的執行過程是每次在文檔中添加新的文字內容,都令HTML編譯器調用一次innerText屬性。加快網頁速度,“快”的例子只調用了一次innerText屬性。 點擊進入演示頁面
慢: | divUpdate.innerHTML = ""; for ( var i=0; i<100; i++ ) { divUpdate.innerHTML += "<SPAN>這是慢的方法! </SPAN>"; } | 快: | var str=""; for ( var i=0; i<100; i++ ) { str += "<SPAN>快是因為使用了字符串! </SPAN>"; } divUpdate.innerHTML = str; | 需要更多信息,請參考Dynamic Content。 關于innerText的討論:
在DHTML對象模型中,HTML文檔的文字內容的添加都是通過innerText來完成的。然而同樣,W3C DOM也提供了一個來實現在一功能的方法。如果您希望在HTML文檔中添加一個節點,那么,使用DOM中的createTextNode方法可以實現。要達到更好更快的效果,還是推薦使用innerText屬性。 | 方法三:使用innerText屬性來改變您的文檔內容。 | 在下面的示例中,展現了如何使用innerText屬性來提高網頁的效率。 點擊進入演示界面
慢: | var node; for (var i=0; i<100; i++) { node = document.createElement( "SPAN" ); node.appendChild( document.createTextNode( " Using createTextNode() " ) ); divUpdate.appendChild( node ); } | 快: | var node; for (var i=0; i<100; i++) { node = document.createElement( "SPAN" ); node.innerText = " Using innerText property "; divUpdate.appendChild( node ); } | 使用DOM來添加單獨的節點:
前面我們已經提到過,為HTML文檔中的添加新的內容,是要調用HTML編譯器的,所以在這期間,必然會有效率上的損失。所以,在添加新的節點的時候,我們聯合調用createElement和insertAdjacentElement方法,而不是僅僅調用一次insertAdjacentElement方法。 | 方法四:調用createElement和insertAdjacentElement方法,比調用insertAdjacentHTML方法快。 | 調用insertAdjacentHTML方法,可能會使您的代碼看起來更加漂亮,但我們不是在這里暢談藝術。在這里,我們直接通過DOM調用他的方法會變得更加有效。 點擊進入演示界面
慢: | for (var i=0; i<100; i++) { divUpdate.insertAdjacentHTML( "beforeEnd", "<SPAN> Uses insertAdjacentHTML() </SPAN>" ); } | 快: | var node; for (var i=0; i<100; i++) { node = document.createElement( "SPAN" ); node.innerText = " Uses insertAdjacentElement() "; divUpdate.insertAdjacentElement( "beforeEnd", node ); } | 在SELECT中添加新的選擇項:
通常我們在動態網頁的需求當中,會碰到需要在下拉菜單中添加新的選擇項,但一般情況下我們只需要添加一兩個就可以解決問題,這個時候我們能夠做到就可以了。但是如果需要添加成百上千個選擇項怎么辦?這時候我們需要使用innerHTML方法而不是為每個需要添加的選項調用一次createElement。 | 方法五:為SELECT添加大數量的選項的時候,使用innerHTML,而不是添加一個調用一次createElement。 | 在下面的例子中,使用了一個字符串。將需要添加的內容用HTML文檔的格式負值給字符串,然后當作一個需要添加在HTML頁中的文字一樣添加到相應的SELECT中,就像方法二種我們討論的那樣。而不是添加一個<option>,調用一次相應的方法。在這其中,我們使用了Microsoft JScript的join方法,來進行最終的<option>節點的拼接。 點擊進入演示界面
慢: | var opt; divUpdate.innerHTML = "<SELECT ID='selUpdate'></SELECT>"; for (var i=0; i<1000; i++) { opt = document.createElement( "OPTION" ); selUpdate.options.add( opt ); opt.innerText = "Item " + i; } | 快: | var str="<SELECT ID='selUpdate'>"; for (var i=0; i<1000; i++) { str += "<OPTION>Item " + i + "</OPTION>"; } str += "</SELECT>"; divUpdate.innerHTML = str; | 更快: | var arr = new Array(1000); for (var i=0; i<1000; i++) { arr[i] = "<OPTION>Item " + i + "</OPTION>"; } divUpdate.innerHTML = "<SELECT ID='selUpdate'>" + arr.join() + "</SELECT>"; | 使用DOM來改變您的表格:
使用DOM中的方法來為自己的表格添加更多的行與列,要比使用insertRow和insertCell兩種方法合算的多。當建立非常大的表格的時候(比如說100行100列,或者更多),這就顯得尤為有效。 下面的例子給出了兩種不同的方法,來為一個表格添加更多的行與列。 點擊進入演示界面
慢: | var row; var cell; for (var i=0; i<100; i++) { row = tblUpdate.insertRow(); for (var j=0; j<10; j++) { cell = row.insertCell(); cell.innerText = "Row " + i + ", Cell " + j; } } | 快: | var row; var cell; var tbody = tblUpdate.childNodes[0]; tblUpdate.appendChild( tbody ); for (var i=0; i<100; i++) { row = document.createElement( "TR" ); tbody.appendChild( row ); for (var j=0; j<10; j++) { cell = document.createElement( "TD" ); row.appendChild( cell ); cell.innerText = "Row " + i + ", Cell " + j; } } | 一勞永逸:
當你的網頁多次用到同一段腳本代碼的時候,不要在每個請求這段腳本的網頁中添加代碼。我推薦的做法是把這段腳本保存在一個文件中,讓每個請求這段代碼的網頁直接去調用那個文件。這樣如果該腳本已經被某個客戶端執行了一次,那么它將被寫在這個客戶端的瀏覽器緩存中,下次調用的時候不必下載這部分內容,從而節省了時間。 | 方法七:將需要多次調用的腳本內容存放在一個文件中,另所有網頁共享這一資源。 | 當然,這一方法也可以擴展到層疊樣式表(CSS)的使用。通常同一站點的網頁都具有相同的風格,從而也就涉及到非常多的樣式的設定。將這些設置保存在一起,作為一個共享資源出現在您的站點中,這樣可以提高網頁的請求速度,同時不影響任何的效果。 不要制作動態效果過多的網頁:
DHTML中的各種功能為開發人員提供了一個非常廣闊的開發空間,它能夠使我們的網頁變得更加具有動感。這是一項偉大的創舉,同時更重要的,它減少了網頁中腳本代碼的數量。但是同樣他也帶來了相應的問題,在執行DHTML中的各種效果的時候,每次都會調用HTML編譯器對代碼進行重新編譯,甚至重新計算網頁中各個元素的具體位置。這一部分在時間以及性能上的開銷往往會令您的網頁看起來不是那么協調。所以,盡量在一篇網頁上不要用到更多的動態效果,這樣會加快網頁的訪問速度。 這一部分就沒有代碼可以演示了 :) 學會使用數據綁定
數據綁定是一個非常強大的功能,適用的情況是,對于現有的一組數據,不必每次動態的調用,而是使用類似于XML data island的功能,加入到現有的HTML文檔中。這樣您不必在網頁中提供一個類似于產看各種功能的函數,取而代之的是一個資料的整體的索引。可能大家不太明白這句話的具體含義。舉個例子說,比如您有一個個人網站,希望把自己的生平事跡全都羅列出來,那可是一項巨大的工程!用普通的方法,每次瀏覽者希望看到您的受教育的情況,讓我們看看這個過程:他在網頁上找到您提供的相應的功能,點擊,向服務器發出請求,通過驗證,在數據庫(如果是的話)找到需要的資料,下載,HTML編譯器重新編譯結果,計算網頁顯示的格式(也就是具體的位置),顯示在您的眼前。哇!看一個簡單的資料需要如此繁瑣的過程,最要命的是還要去服務器請求結果!如果此時服務器很慢呢?所以我們的解決方案是數據綁定,將所有數據綁定到客戶端,瀏覽者就可以不用通過請求服務器做到同樣的事情,并且效率是原先的好幾倍,更重要的是,您的網頁上省去了那些討厭的功能按鈕,這樣就能更加快速的在本地瀏覽。 | 方法九:使用數據綁定,為客戶端提供更多更快的數據資源。 | 這一部分也沒有代碼可以演示 :) 不要在document中使用屬性額外的屬性 DHMTL中提供了一個功能,可以自己定義屬性,這樣我們就能用自己定義的屬性來存放更多的有用的資料。例如,我們可以自己定義一個事件叫做mouseover,當真正的onmouseover引發的時候引發自己定義的函數(類似于HTC)。但是千萬記住,不要在document對象中使用這樣的技術。 點擊進入演示界面
慢: | for (var i=0; i<1000; i++) { var tmp; window.document.myProperty = "Item "+i; tmp = window.document.myProperty; } | 快: | for (var i=0; i<1000; i++) { var tmp; window.myProperty = "Item "+i; tmp = window.myProperty; } | 關于Class與CSS:
如果您的網頁提供了不同的閱覽風格,這需要我們對同一個元素,定義很多不同的樣式。最好的方法是,直接修改該元素的style,而不是改變這個元素的className。 | 方法十一:改變元素樣式,直接修改該元素style,不要改變它的className。 | 這部分也沒有代碼 :) 寫在最后
上面討論了一些小的技巧,如何使動態網頁的訪問變得更加快速,這在我們平時的工作中,是絕對用的到的。如果您是一個初學網頁設計的人,那么這篇文章可能并不適合您。 如果大家有更多好的建議,好的方法,好的技巧,我希望與大家作進一步的交流。您可以點擊左邊的“評注”,把您想說的都留在那里,或者您也可以給我發信,我的個人郵箱是:onefi@frontfree.net
|