JavaScript_DOM編程藝術第二版學習筆記-第5章

第五章 平穩退化

主要目的,讓那些不支持或者禁用了javascript功能的瀏覽器也能順利訪問網站。

5.1彈出窗口

JS使用window對象的open()方法創建新的瀏覽器窗口,語法:

window.open(url,name,features)

三個參數是可選的。

  • 參數1是想在新窗口中打開的網頁的URL地址。若省略這個參數,屏幕上將彈出一個空白的瀏覽器窗口。
  • 參數2是新窗口的名字,可在代碼裏通過這個名字與新窗口進行通信
  • 參數3是一個以逗號分隔的字符串,其內容是新窗口的各種屬性(窗口尺寸等)。需注意:新窗口的瀏覽功能要少而精。

open()方法是使用BOM的一個很好的案例,它的功能對文檔的內容也無任何影響,至於瀏覽環境有關。如下實例:

functio popUp(winURL){
window.open(winURL,"popup","width=320,height=480");
}

這個函數經打開一個寬爲320,高爲480的新窗口“popup”。

5.2“JavaScript:”僞協議

真協議用來在因特網上的計算機之間傳輸數據包,如HTTP協議(http://)、FTP協議(ftp://),僞協議則是一種非標準化的協議。“javaScript:”讓我們通過一個鏈接來調用JavaScript函數。

<a href="javascript:popup('http://www.ecample.com/');">Example</a>

在支持“javascript:”僞協議的瀏覽器中運行正常,較老瀏覽器會嘗試打開那些鏈接但失敗,支持這種僞協議但禁用了JavaScript功能的瀏覽器則什麼都不做。
總之,在文檔裏通過這種僞協議調用JavaScript代碼的做法非常不好。

5.3 向CSS學習

作爲CSS技術的突出優點,文檔結構與文檔樣式的分離可以確保網頁都能平穩退化,具備CSS支持的瀏覽器可以呈現美輪美奐的網頁,不支持或禁用了CSS的瀏覽器同樣可以把網頁內容按照正確的結構顯示出來。

5.3.1 漸進增強

所謂的漸進增強就是用些額外的信息層取包裹原始數據。類似於CSS、JS和DOM提供的所有功能也應該構成一個額外的指令層。CSS負責提供關於“表示”的信息,JS負責提供關於“行爲”的信息。行爲層的應用方式與表示層類似。
CSS與HTML的分離可以讓CSS工作的更好,同樣適用於JS行爲層。

5.4 分離JavaScript

雖然將JS與HTML分的很開了,實際負責完成各項任務的JS函數都已存入外部文件中,但是還有 內嵌的事件處理函數可以進一步分離。
類似於使用style屬性,HTML文檔裏的onclick屬性也是一種既沒效率又易引發問題的做法。如果我們用CSS機制中的class或id屬性那樣,把JS代碼調用行爲與HTML文檔結構和內容分離,網頁就會健壯得多。
把一個事件添加到HTML文檔中的某個元素上:

getElementById("id").event = action...

實例:

var links = document.getElementsByTagName("a");
for (var i = 0; i <links.length; i++) {
 if (links[i].getAttribute("class") == "popup") {
    links[i].onclick = function (){
        popUp(this.getAttribute("href"));
        return false;
        }
    } 
 }

如上實例在沒有完整的DOM情況下,getElementByTagName等方法不能夠正常工作。
必須讓這些代碼在HTML文檔全部加載到瀏覽器之後馬上開始運行。還好,文檔將被加載到一個瀏覽器窗口裏,document對象又是Window對象的一個屬性。當window對象觸發onload事件時,document對象已經存在。
我將把我的JS代碼打包在prepareLinks函數裏,並把這個函數添加到window對象的onload事件上去。這樣一來,DOM就可以正常工作了。

window.onload = prepareLinks;
function prepareLinks(){
    var links = document.getElementsByTagName("a");
    for (var i = 0; i <links.length; i++) {
        if (links[i].getAttribute("class") == "popup") {
            links[i].onclick = function (){
            popUp(this.getAttribute("href"));
            return false;
        }
    } 
 }
}

5.5 向後兼容

5.5.1 對象檢測

幾乎所有東西(包括方法在內)都可以被當作對象,意味着我們可以吧不支持某個特定DOM方法的瀏覽器檢測出來:

if(method){statements}

function myFunction(){
    if (document.getElementsByTagName) {
        statements using getElementsByTagName
    };
}

需注意的是,if裏的方法不要加(),否則判斷的是方法的結果,無論方法是否存在。
同樣,如果存在多個檢測,如上的代碼就會顯得很冗長,我們需要把測試條件從“如果你理解…”改爲“如果你不理解….”,需要使用“邏輯非”操作符,即if(!method),用來測試getElementById是否存在的語句可以改爲如下:
if(!getElementById) return false; 這就類似於說,如果你不是別getElementById,那就直接退出吧。
若有多個測試存在,只需加上“邏輯或”操作符將其合併,如下:if(!getElementById || !getElementsByTagName) return false;
雖然只是一條簡單的if語句,但它可以確保那些古老的瀏覽器不會因爲我的腳本代碼而出現問題。這樣實現了腳本良好的向後兼容性。因爲我在給網頁添加各種行爲時始終遵循“漸進增強”的原則,所以確定我添加的那些都能平穩退化,我的網頁在那些“古老的”瀏覽器裏也能正常瀏覽,在那些只支持部分JavaScript功能但不支持DOM的瀏覽器仍可訪問我網頁的內容。

5.6 性能考慮

5.6.1 儘量少訪問DOM和儘量減少標記

訪問DOM的方式對腳本性能會產生非常大的影響。以下爲例:

if (document.getElementsByTagName("a").length>0) {
    var links = document.getElementsByTagName("a");
    for (var i = 0; i < links.length; i++) {
        links[i]
        //對每個鏈接做點處理
    };
};

雖然這段腳本可以正常運行,但是仔細看下,居然兩次使用了getElementsByTagName這個方法去搜索同一個標籤,真是一種搜索浪費。不管什麼時候,只要是查詢DOM樹中的某些元素,瀏覽器便會搜索整個DOM樹。更好的辦法是將第一次搜索的結果存儲在一個變量中,以後重複使用該變量。改良後的代碼如下:

var links = document.getElementsByTagName("a");
if (links.length>0) {   
    for (var i = 0; i < links.length; i++) {
        links[i]
        //對每個鏈接做點處理
    };
};

這樣一來,代碼功能沒變,但搜索DOM的次數有兩次降低到了一次。
如果有多個函數重複做同一件事,可能不太好發現。比如,一個函數檢查每個連接中的popup類,另一個函數檢查每個連接中的hover類,那麼同樣也會造成搜索浪費。在多個函數都會取得一組類似元素的情況下,可考慮重構代碼。把搜索結果保存在一個全局變量裏,或者把一組元素直接以參數形式傳遞給函數。
另外一個需注意,儘量減少文檔中的標記數量。過多不必要的元素只會增加DOM樹的規模,進而增加遍歷DOM樹以查找特定元素的時間。

5.6.2 合併和放置腳本

常見的腳本引用,如下的這種情況,最好也不要出現:

<script src="script/functionA.js"></script>
<script src="script/functionB.js"></script>
<script src="script/functionC.js"></script>
<script src="script/functionD.js"></script>

推薦做法是將functionA、functionB、functionC、functionD都合併到一個腳本文件中,這樣可以減少加載頁面時發送的請求數量。減少請求數量通常是性能優化首先考慮項。
同樣的,根據漸進增強的原理,應該把<script>標籤放在</body>之前,讓頁面變得更快。

5.6.3 壓縮腳本

除了以上做法,還有一樣操作也可用來加快網頁加載速度:壓縮腳本。
所謂壓縮,指的是把腳本文件中不必要的字節,如空格、註釋、統統刪除。目前有許多工具可用來壓縮腳本。
壓縮精簡後的代碼雖不易看懂,卻能大幅減少文件的大小。多數情況下,應該有兩個腳本的版本。一個是工作副本,可用來修改代碼並添加註釋;另一個是精簡副本,用於放在站點上。爲了便於區分這兩個版本,最好在精簡版本的文件名加上min字樣:

<script src="script/functionB.min.js"></script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章