[筆記6]JavaScript DOM編程藝術_最佳實踐

本章內容

  • 平穩退化 確保網頁在沒有JS的情況下也能正常工作。
  • 分離JS 把網頁的結構和內容與JS腳本的動作行為分開
  • 向后兼容性 確保老版本的瀏覽器不會因為你的JS腳本而死掉
  • 性能考慮 確定腳本執行的性能最優

平穩退化

如果正確地使用了JS腳本,就可以讓訪問者在他們的瀏覽器不支持JS的情況下仍能順利地瀏覽你的網站,這就是平穩退化

JS使用window對象的open()方法來創建新的瀏覽器窗口。這個方法有三個參數:window.open(url,name,features)

  • url新窗口里打開的網頁的URL地址
  • 新窗口的名字,可以在代碼里通過這個名字與新窗口進行通信。
  • 以逗號分隔的字符串。其內容是新窗口的各種屬性。
function popUp(winURL) {
    window.open(winURL,"popUp","width=320,height=480");
}

調用popUp函數的一個辦法就是使用偽協議。
真協議用來在因特網上的計算機之間傳遞數據包,如http協議、ftp協議。偽協議是一種非標準化的協議。“javascript:”偽協議讓我們通過一個鏈接來調用JS函數。

具體做法:

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

這條語句在支持“javascript:”偽協議的瀏覽器中運行正常,較老的瀏覽器則會嘗試打開鏈接失敗,支持這種偽協議但禁用了JS功能的瀏覽器會什么也不做。

總之,在html文檔里通過javascript:偽協議調用JavaScript代碼的做法非常不好。

內嵌的事件處理函數

把onclick事件處理函數作為屬性嵌入a標簽,改處理函數將在onclick事件發生時調用圖片切換函數。

<a href="#" onclick="popUp('http://www.example.com');return false;">Example</a>

因為在上面這條HTML指令里使用了return false語句,這個鏈接不會被真的打開。“#”符號是一個僅供文檔內部使用的鏈接符號。把href屬性值設置為“#”只是為了創建一個空鏈接。實際工作全部由onclick屬性負責完成。

但是上面的技巧都不能平穩的退化,如果用戶已經禁用了瀏覽器的JS功能,這樣的鏈接毫無用處。

具體到popUp()函數,為其中的JS代碼預留出退路很簡單。在鏈接里把href屬性設置為真實存在的URL地址,讓它成為一個有效的鏈接。

<a  onclick="popUp('http://www.example.com';return false;)">Example</a>
//-------------用this簡化一下-------------//
<a  onclick="popUp(this.getAttribute('href');return false;)">Example</a>
//-------------更簡單的方式-------------//
<a  onclick="popUp(this.href);return false">Example</a>

在本書此前介紹的所有技巧當中,這個技巧最有用,但是它還有改進的余地。最明顯的不足時:每當需要打開新窗口時,就不得不把一些JS代碼嵌入標記文檔中。如果能把事件處理函數在內的所有JS代碼全都放在外部文件里,這個技巧將更加完善

向CSS學習

CSS是一項了不起的技術。CSS可以讓人們對網站設計工作中的各個方面做出嚴格細致的控制。

標記良好的內容就是一切

PS:上面這句話深有感觸。

分離JS

JS語言不要求事件必須在HTML文檔里處理。我們可以在外部JS文件里吧一個事件添加到HTML文檔中的某個元素上。element.event=action...
關鍵是怎樣才能把應該獲得這個事件的元素確定下來。這個問題可以利用class或者id來解決。

如果想把一個事件添加到某個帶有特定id屬性的元素上,用getElementById就可以解決問題:getElementById(id).event=action。如果事件涉及到多個元素,我們可以用getElmentsByTagName和getAttribute把事件添加到有著特定屬性的一組元素上。

具體步驟:

  • 把文檔里的所有鏈接全放入一個數組里。
  • 遍歷數組。
  • 如果某個鏈接的class屬性等于popup,就表示這個鏈接在被點擊時應該調用popUp()函數。

于是,

  • 把這個鏈接的href屬性值傳遞給popUp()函數;
  • 取消這個鏈接的默認行為,不讓這個鏈接把訪問者帶離當前窗口。
var links=document.getElementByTagName("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;
     }
}
}

如果把上面這段代碼存入外部JS文件中,它們將無法正常運行。因為代碼的第一行是var links=document.getElementsByTagName("a");這句話將在JS文件被加載時立刻執行。如果JS文件是從HTML文檔的< head>部分用<script>標簽調用的,它將在HTML文檔之前加載到瀏覽器里。同樣,如果標簽位于文檔底部</body>之前,就不能保證哪個文件最先結束加載(瀏覽器可能加載多個),因為腳本加載時文檔可能不完整,所以模型也不完整,沒有完整的DOM,getElementByTagName等方法就不能正常工作。必須讓這些代碼在HTML文檔全部加載到瀏覽器之后馬上開始執行。

HTML文檔加載完畢時將觸發一個事件,文檔將被加載到一個瀏覽器窗口里,document對象又是window對象。當window對象觸發onload事件時,document對象已經存在

window.onload=prepareLinks;
funciton 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;
            }
         }
      }
}

向后兼容

對象檢測

判斷瀏覽器是否對DOM支持,最簡單的解決方案是,檢測瀏覽器對JS的支持程度。解決方案:只要把某個方法打包在一個if語句中,就可以根據這條if語句的條件表達式的求值結果是true還是false來決定采取怎樣的行動。這種檢測稱為對象檢測。

例如,如果有一個使用了getElementById()方法的函數,就可以在調用getElementById()方法之前先檢查用戶所使用的瀏覽器是否支持這個方法。**在使用對象檢測時,一定要刪掉方法后面的圓括號,如果不刪掉,測試的將是方法的結果。無論方法是否存在。

function myFunction(){
     if(document.getElementById){
      statements using getElementById
     }
}

為了避免上面的方法,增加邏輯的深度,可以使用下面的方式。

if(!getElementById){
   return false;
}
//------------如果要檢測多個方法或著屬性是否存在,可以使用“邏輯或”
if(!getElementById||!getElementByTagBName){
   return false;
}

上面的例子增加JS是否支持DOM的語句如下:

window.onload=prepareLinks;
function prepareLinks(){
if (!document.getElementsByTagName) {return false;}
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;
        }
    }   
}
}

瀏覽器嗅探技術

瀏覽器嗅探 指通過提取瀏覽器供應商提供的信息來解決向后兼容問題。從理論上講,可以通過JS代碼檢索關于瀏覽器品牌和版本的信息,這些信息可以用來改善JS腳本代碼的向后兼容性。

PS:瀏覽器嗅探技術充滿風險,逐漸被對象檢測技術所取代。主要是兩個原因,一個是瀏覽器會撒謊,你無法獲得準確的版本或者品牌信息。第二是瀏覽器嗅探器腳本是對版本信息進行精確匹配,版本信息變化太快,腳本所做的修好會比較多。

性能考慮

盡量少訪問DOM和盡量減少標記

訪問DOM方式對腳本性能會產生非常大的影響。不管什么時候,只要查詢DOM中某些元素,瀏覽器都會搜索整個DOM樹,從中查找可能匹配的元素。
另一個需要注意的地方,就是要盡量減少文檔中的標記數量。過多不必要的元素只會增加DOM樹的規模,進而增加遍歷DOM樹以查找特定元素的時間。

合并和放置腳本

將多個js文件合并到一個文件中,這樣就可以減少加載頁面時發送的請求數量。而減少請求數量通常都是在性能優化時首先要考慮的。

把所有script標簽都放到文檔的末尾,body標記之前,就可以讓頁面變得更快。

壓縮腳本

壓縮腳本可以加快加載速度。

所謂壓縮腳本,指的是把腳本文件中不必要的字節,如空格和注釋,統統刪掉,從而達到壓縮文件的目的。精簡后的代碼雖然不容易看懂,卻能大幅減少文件大小。多數情況下,你應該有兩個版本。一個是工作副本,可以修改代碼并添加注釋;另一個是精簡副本,用于放在站點上。通常為了將精簡版本與非精簡版本區分開,最好在精簡副本的文件名上加上min字符。

推薦的幾個代表性的代碼壓縮工具:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容