JS魔法堂:LINK元素深刻詳解

1、前言                            javascript

  咱們通常使用方式爲 <link type="text/css" rel="stylesheet" href="text.css"> 來引入外部層疊式樣式文件,但LINK元素各屬性的具體含義、資源加載行爲等方面卻瞭解很少,本文打算稍微深刻一下。css

  因爲內容較多,特設目錄一坨:html

  2、到底有沒有結束標籤?java

  3、普通屬性介紹web

  4、屬性disabled詳解正則表達式

    1. Attribute和Property的disabled瀏覽器

  2. disabled爲true還會加載樣式文件嗎?緩存

    3. disabled爲true還會觸發onload、onerror和onreadystatechange事件嗎?網絡

    4. CSS解析app

  5. 渲染

  5、屬性rel介紹

  6、動態建立LINK元素

  7、與資源加載相關的屬性和事件

  8、資源加載實驗

  1. IE下的結論

  2. Chrome下的結論

  3. FF下的結論

  9、總結

  10、參考

 

2、到底有沒有結束標籤?                    

  也許咱們經常會看到一下兩種寫法

<!-- 無結束標籤 -->
<link type="text/css" rel="stylesheet" href="test.css">
<!-- 閉合標籤 -->
<link type="text/css" rel="stylesheet" href="test.css"/>

  參考官網可知:

在 HTML 中,<link> 標籤沒有結束標籤。

在 XHTML 中,<link> 標籤必須被正確地關閉。

3、普通屬性介紹                          

  1.  屬性media ,指定該樣式應用到的顯示設備(媒介類型),默認值爲all,還有值screen(顯示器)和print(打印機)被瀏覽器支持。另外還有一堆爲成爲事實標準的值。

  2.  HTML5屬性sizes ,用於指定網頁圖標高寬(格式: 高x寬 或默認值 any ),須要同時配置 rel="icons" ,示例:

<link type="images/png" href="fsjohnhuang.png" rel="icons" sizes="16x16"/>

  3.  屬性type ,引入的資源MIME類型,注意:不規定必須爲text/css。

4、屬性disabled詳解                       

  下列內容主要參考《HTML中Link元素disable屬性詳解》的內容,並補充一些實踐過程當中踩過的坑。

  1. Attribute和Property的disabled(若想了解更多屬性、特性的信息可參考《JS魔法堂:屬性、特性,傻傻分不清楚》

    因爲disabled屬於標準屬性,所以能夠經過點方式(property)和getAttribute方式(Attribute)對其進行操做。對於IE和Chrome,二者是同步的。但對於FF來講二者是分離的。

   1. 對於靜態引入LINK元素,且經過Attribute方式設置disabled爲true,因爲Attribute和Property是分離的,此時FF下經過點方式操做的disabled依然爲false(而IE、Chrome的則爲true),而是否應用到元素渲染上則由點方式操做的disabled的值來決定,所以該方式在FF下依然會應用到元素渲染上,而在IE和Chrome上則不會應用到元素渲染上。

<link type="text/css" rel="stylesheet" href="text.css" disabled="true"/>

   2. FF中須要靜態或動態引入LINK元素時,都必須等LINK元素被添加到渲染樹中後才能夠經過點方式修改disabled,不然修改無效,disabled值一直爲false。

複製代碼
// FF下
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'test.css';
console.log(link.disabled); // false
link.disabled = true;
console.log(link.disabled); // false
// 加入DOM樹,還未加入渲染樹
document.body.appendChild(link);
link.disabled = true;
setTimeout(function(
    console.log(link.disabled); // false  
    link.disabled = true;
    console.log(link.disabled); // true
), 0);
複製代碼

  2. disabled爲true還會加載樣式文件嗎?

     僅Chrome在disabled爲true時,不加載樣式文件。其餘瀏覽器均依然繼續加載文件資源。

  3. disabled爲true還會觸發onload、onerror和onreadystatechange事件嗎?

  因爲FF下經過Attribute方式設置disabled爲true,和在LINK元素未加入渲染樹前修改disabled爲true均無效,所以僅FF下會觸發onload和onerror事件。其餘瀏覽器均不會觸發onload、onerror和onreadystatechange事件。

     因爲FF下存在上述特性,所以能夠經過以下手段設置FF下的樣式的disabled爲true。

<link id="test" type="text/css" rel="stylesheet" href="test.css" onload="this.disabled=true;"/>

  4. CSS解析

     首先須要理解的是CSS解析究竟是什麼?

   其實就是在成功加載樣式文件後,將樣式文件中的樣式添加到樣式表document.styleSheets中。而應用到元素渲染的樣式則爲document.styleSheets的子集。

     因爲對於disabled爲true的LINK元素,Chrome將不加載其樣式文件,所以也沒法將文件中的樣式添加到document.styleSheets中;也只有Chrome在將disabled屬性從false動態修改成true時,會從document.styleSheets中刪除該樣式文件的樣式。其餘瀏覽器只要成功加載樣式文件就會將其中的樣式添加到document.styleSheets中,不管disabled屬性值是什麼。

  5. 渲染(頁面元素與CSS屬性結合呈現到頁面上)

     只要LINK元素的點方式的disabled爲true,那麼它所關聯的樣式規則均不生效。(FF則須要通過上述的特殊處理)

  對於想經過樣式文件書寫樣式規則,但又想經過document.styleSheets按需提取應用樣式的狀況,因爲Chrome採用直接不加載樣式文件的處理方式,所以須要經過以下手段處理:

<link id="test" type="text/css" rel="stylesheet" href="test.css" onload="this.disabled=true;"/>

 

5、屬性rel介紹                        

  屬性rel用於規定當前文檔與被加載的資源之間的關係。

  1. 定義網站收藏夾圖標

<link rel="shortcut icon" href="http://paranimage.com/wp-content/themes/v5/images/favicon.ico" type="images/x-icon"/>
<link rel="icon" href="http://paranimage.com/wp-content/themes/v5/images/favicon.png" type="images/png"/>

     IE下rel必須爲 shortcut icon ,並且圖標必須爲 .ico格式  。而其餘瀏覽器的rel只需寫爲 icon ,圖標不必定須要使用 .ico格式 。

  2. 定義蘋果桌面上的網站圖標

<link rel="apple-touch-icon" href="http://paranimage.com/wp-content/themes/v5/images/apple-touch-icon.png" />

  3. RSS地址和Pingback地址

<link rel="alternate" type="application/rss+xml" title=" RSS Feed" href="rss.html" />
<link rel="alternate" type="application/atom+xml" title="Atom Feed" href="atom.html" />
<link rel="pingback" href="pingback.html" />

 

六 、動態建立LINK元素                    

  動態建立元素通常有兩種方式,分別是document.createElement方法和innerHTML+firstChild。對於LINK元素,在IE9+和其餘現代瀏覽器中可以使用innerHTML+firstChild方式建立LINK元素,而在IE5~8中則須要使用document.createElement方式建立。下面代碼爲簡單的實現方式:

複製代碼
var $ = function(){
   // 提取tagName、attributes總體和innerHTML
  var rTag = /<([a-z]+)\s*([^>]*)(?:\/>|>([^<]*)<\/\1>)/ig,
       // 提取attribute的鍵值
       rAttrs = /\s*([a-z]+)\s*=("|')([^'"]*)\2\s*/ig;
   // IE9+和其餘瀏覽器的DOM對象生成工廠
   var factory = document.createElement('div');
   return function(html){
    var el = (factory.innerHTML = html, factory.firstChild);
      if (!el){
        var baseInfo = rTag.exec(html);
         try{
           el = document.createElement(baseInfo[1]);
            var innerHTML = baseInfo[baseInfo.length - 1];
            if (innerHTML !== null && typeof innerHTML !== 'undefined' && innerHTML !== '')
              el.innerHTML = innerHTML;
                var attrStr = baseInfo[2];
                var groups;
                while(groups = rAttrs.exec(attrStr))
                  el.setAttribute(groups[1], groups[3]);
            }
         catch(e){
          return null;
         }
         // 重置正則表達式
         rTag.compile(rTag);
         rAttrs.compile(rAttrs);
      }

      return el;
   };
}();
複製代碼

 

7、與資源加載相關的屬性和事件                  

  資源加載首先固然是肯定資源位置的 href屬性 ,隨之就是資源加載成功與否的 onload事件 和 onerror事件 ,對於IE5~8還多了一個 onreadystatechange事件 和與之相關的 readyState屬性 

   onload事件 ,當資源加載完成後觸發(注意:即便資源類型與LINK元素的type屬性值不符,只要資源加載完成就會觸發onload事件)。

   onerror事件 ,當找不到資源時會觸發(注意:IE5~11不管任何狀況均不會觸發該事件)

   onreadystatechange事件 ,IE5~10下readyState變化就會觸發該事件。

   readyState屬性 ,用於表示LINK元素當前的資源裝載狀態,默認值爲"uninitialized",資源加載中爲"loading",資源加載完成爲"complete"(注意:資源加載完成不表明資源被成功加載)

 

8、資源加載實驗                        

    本次實驗將建立 LINK元素 並對其的 href屬性 分別賦予如下內容 test.css 、 fsjohnhuang.png 、 :0 、 空字符串 、 空白字符串 、 //:0 、 javascript:void 0 和 data:image/png,foo 。並訂閱img元素的onload和onerror事件,IE5~10下還訂閱了onreadystatechange事件,統計整理其在IE5~十一、Chrome和FF下的行爲特色和事件響應延時。具體實驗統計以下:

    測試環境:

  1. 測試頁面地址爲http://localhost:9000/test.html

    2. 圖片fsjohnhuang.png的大小爲12KB

      3. test.css的大小爲0KB

      4. LINK元素已加入渲染樹,rel屬性值爲stylesheet,disabled屬性爲false(注意:FF下disabled爲true,依然會觸發事件)

    LINK元素加載資源的前提是加入到渲染樹,rel屬性值有效(Chrome下則還須要disabled爲false)。

      5. 經過DOM 0方式訂閱事件

    符號說明:

   N/A 表示該列事件不觸發

href屬性值 備註 Chrome FireFox IE5~11
onload事件 onerror事件 備註 onload事件 onerror事件 備註

IE11

onload事件

IE11

onerror事件

IE5~10

on

ready

state

change

備註
test.css

有效URI,

URI自動補全爲

http://localhost

:9000/test.css

 首次延時爲5ms  N/A  後續讀取緩存爲0~1ms  首次延時爲5ms  N/A 後續讀取緩存爲0~1ms   首次onload延時9ms,後續讀取緩存則爲0~1ms  N/A

 1. 首次加載時,先觸

發兩次onreadystate

change事件,從"uninitialized"->"loading"->

"complete"。而後

觸發onload事件。

2. 後續則從緩存中加載

資源,先觸發一次onreadystatechange

事件,從"unitialized"->"complete"。而後觸

發onload事件。

 
fsjohnhuang.png  

有效URI,

URI自動補全爲

http://localhost

:9000/fsjohnhu

ang.png

 首次延時爲4ms  N/A  後續讀取緩存爲0~2ms  N/A  延時爲3~7ms  不會緩存資源  延時爲7~33ms  N/A

IE9~10中 

觸發兩次onreadystatechange

事件(延時0~2ms, 10~12ms),

"unintialized"->

"loading"->

"complete",

。而後

觸發onload事件

(延時爲6~22ms) 不會對資源進行緩存

IE5~8中

1.首次加載會發起請求,

會觸發兩次onreadystatechange

事件,"uninitialized"-

>"loading"->

"complete"。而後

在觸發onload事件,緩存資源;

2.後續加載會從緩存

讀取資源,觸發一次onreadystatechange

事件,"uninitialized"

->"complete"。而後

在觸發onload事件。

 
:0  

無效URI,

URI自動補全爲http://localhost

:9000/:0

 N/A  延遲爲6~300ms  發起網絡請求,返回404 HTTP狀態碼   N/A  延遲爲13~30ms  發起網絡請求,返回404 HTTP狀態碼  延遲爲10ms左右  N/A

 觸發兩次onreadystatechange

事件(延時0~2ms, 10~12ms),

"unintialized"->

"loading"->

"complete",而後在

觸發onload事件(延時11~13ms)

  發起網絡請求,返回404 HTTP狀態碼
空字符串,""  無效URI  N/A  N/A  不發起請求  N/A  N/A   不發起請求  延時爲0~1ms  N/A

IE9~10中

 1.首次加載,僅會觸發onreadystatechange

事件,且僅從

"unitialized"->

"loading";

2.後續加載,

先觸發兩次onreadystatechange

事件,且從

"unitialized"->"complete",

而後再觸發onload事件

IE5~8中

1.首次加載,僅會觸發

onreadystatechange

事件,且僅從

"unitialized"->

"loading";

2.後續加載,

先觸發一次onreadystatechang

e事件,且從

"unitialized"->"complete",

而後再觸發onload事

 不發起網絡請求
空白字符串,"    "  無效URI  N/A  N/A  不發起請求  N/A  延時爲3~7ms  不會對資源進行緩存  延時爲5~22ms  N/A

IE9~10中

觸發一次onreadystatechange

事件,

"uninitialized"-

>"loading"->

"complete"。

而後在觸發onload事件。不會緩存資源

IE5~8中

1.首次加載會發起請求,

會觸發兩次onreadystatechange

事件,"uninitialized"-

>"loading"->

"complete"。而後

在觸發onload事件,緩存資源;

2.後續加載會從緩存

讀取資源,觸發一次onreadystatechange

事件,"uninitialized"

->"complete"。而後

在觸發onload事件。

 
//:0  無效URI,會自動補全爲http://:0/  N/A   N/A  不發起請求  N/A  延時爲1~4ms  不會對資源進行緩存  延時爲0~1ms  N/A

IE9~10中

觸發兩次onreadystatechange

事件(延時0~2ms, 5~8ms),readyState

均爲"complete",

而後在觸發onload事件

(延時5~9ms)

IE5~8中

觸發一次onreadystatechange

事件(延時3ms),readyState爲

"complete",

而後在觸發

onload事件

(延時5~8ms)

不會緩存資源
javascript:void 0  無效的JavaScript URI Scheme  N/A  延時爲0~8ms  發起網絡請求,但瀏覽器會取消該請求  N/A  延時爲0~3ms  發起網絡請求,但瀏覽器會取消該請求  N/A  N/A

IE8~10中

會觸發一次onreadystatechage

事件(2~4ms),

"uninitialized"

->"loading"

IE5~7中

每次加載均會在設置

`link.href=

"javascript:void 0";`

時會報「沒法設置href

屬性。已停止操做」的

異常,但後面依然會

觸發一次onreadystatechage

事件(2~4ms),

"uninitialized"->"loading"

 資源一直處於加載未完成的狀態
data:image/png,f  無效的Data URI Scheme  延時爲0~7ms  N/A  不會觸發網絡請求  N/A  延時爲0~2ms  不會觸發網絡請求  延時爲0~1ms  N/A

IE9~10中

觸發兩次onreadystatechange事件(延時1~2ms, 5~8ms),readyState均爲"complete",而後在觸發onload事件(延時5~9ms)

IE5~8中

觸發一次onreadystatechange事件(延時3ms),readyState爲"complete",而後在觸發onload事件(延時5~8ms)

 不會觸發網絡請求

    從表格數據獲得如下規律:

    IE下

  1. onerror絕對不會被觸發;

      2. IE5~8中的onload事件均在readyState爲"complete"且onreadystatechange事件觸發後才觸發,對於IE11中沒有readyState屬性和onreadystatechange事件,則參考IE5~8中的readyState,若能轉換爲"complete"則會觸發onload事件。

      3. 對於有效樣式資源(如test.css),首次加載readyState值從"uninitialized"->"loading"->"complete",而後緩存資源;後續對加載同一資源時則從緩存讀取,readyState值從"uninitialized"->"complete"。

      4. 對於與資源MIME類型與type屬性值不符的資源(如fsjohnhuang.png,空白字符串),IE9~11均不會對資源進行緩存,且readyState值從"uninitialized"->"loading"->"complete";而IE5~8則會對資源進行緩存,readyState值從"uninitialized"->"complete"。

      5. 對於無效路徑的HTTP URI Scheme資源(如:0),IE5~11均不會對資源進行緩存,readyState值從"uninitialized"->"loading"->"complete";

      6. 對於空字符串,IE行爲十分詭異,IE9~10中首次加載readyState值從"uninitialized"->"loading",後續加載則觸發兩次onreadystatechange事件,且readyState值從"unintialized"->"complete"->"complete"。IE5~8中首次加載readyState值從"uninitialized"->"loading",後續加載則觸發一次onreadystatechange事件,readyState值從"unintialized"->"complete"。

      7. 對於//:0,IE會取消網絡請求,IE9~10中會觸發兩次onreadystatechange事件,且readyState值從"unintialized"->"complete"->"complete"。IE5~8中觸發一次onreadystatechange事件,且readyState值從"unintialized"->"complete"。

  8. 對於JavaScript URI Scheme資源(如javascript:void 0),IE行爲較爲統一,均觸發一次onreadystatechange事件,且readyState值從"unintialized"->"loading"。而IE5~7會在執行a.href='javascript:void 0'時報"沒法設置href屬性。已停止操做」的異常。

      9. 對於Data URI Scheme資源(如data:image/png,f),IE行爲較爲統一,均會觸發onreadystatechange事件,且readyState值從"unintialized"->"complete"。區別在於IE9~10觸發兩次事件,IE5~8觸發一次。

   Chrome下

  1. 對於有效路徑資源(如test.css,fsjohnhuang.png),均加載並緩存起來,而後觸發onload事件;

      2. 對於空字符串、空白字符串和//:0,均不做爲;

      3. 對於無效路徑的HTTP URI Scheme資源(如:0),觸發onerror事件;

      4. 對於JavaScript URI Scheme資源(如javascript:void 0),瀏覽器會取消其網絡請求,觸發onerror事件;

  5. 對於Data URI Scheme資源(如data:image/png,f),無論資源是否有效均觸發onload事件。

 FF下

  1. 對於有效路徑資源且資源類型與type屬性值匹配的(如test.css),將加載並緩存起來,而後觸發onload事件;

      2. 對於無效路徑資源或資源類型與type屬性值不匹配的(如fsjohnhuang.png,:0,//:0,空白字符串),則觸發onerror事件;

      3. 對於空字符串,則不做爲;

      4. 對於JavaScript URI Scheme資源(如javascript:void 0),瀏覽器會取消其網絡請求,觸發onerror事件;

  5.  對於Data URI Scheme資源(如data:image/png,f),資源有效則觸發onload事件,無效則觸發onerror事件。

相關文章