一、前言
我們一般使用方式為 <link type="text/css" rel="stylesheet" href="text.css"> 來引入外部層疊式樣式文件,但LINK元素各屬性的具體含義、資源加載行為等方面卻了解不多,本文打算稍微深入一下。
由于內容較多,特設目錄一坨:
1. Attribute和Property的disabled
3. disabled為true還會觸發onload、onerror和onreadystatechange事件嗎?
也許我們常常會看到一下兩種寫法
<!-- 無結束標簽 --> <link type="text/css" rel="stylesheet" href="test.css"> <!-- 閉合標簽 --> <link type="text/css" rel="stylesheet" href="test.css"/>
參考官網可知:
在 HTML 中,<link> 標簽沒有結束標簽。
在 XHTML 中,<link> 標簽必須被正確地關閉。
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。
下列內容主要參考《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);
僅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;"/>
首先需要理解的是CSS解析到底是什么?
其實就是在成功加載樣式文件后,將樣式文件中的樣式添加到樣式表document.styleSheets中。而應用到元素渲染的樣式則為document.styleSheets的子集。
由于對于disabled為true的LINK元素,Chrome將不加載其樣式文件,因此也無法將文件中的樣式添加到document.styleSheets中;也只有Chrome在將disabled屬性從false動態修改為true時,會從document.styleSheets中刪除該樣式文件的樣式。其他瀏覽器只要成功加載樣式文件就會將其中的樣式添加到document.styleSheets中,無論disabled屬性值是什么。
只要LINK元素的點方式的disabled為true,那么它所關聯的樣式規則均不生效。(FF則需要經過上述的特殊處理)
對于想通過樣式文件書寫樣式規則,但又想通過document.styleSheets按需提取應用樣式的情況,由于Chrome采用直接不加載樣式文件的處理方式,因此需要通過如下手段處理:
<link id="test" type="text/css" rel="stylesheet" href="test.css" onload="this.disabled=true;"/>
屬性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" />
動態創建元素一般有兩種方式,分別是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; }; }();
資源加載首先當然是確定資源位置的 href屬性 ,隨之就是資源加載成功與否的 onload事件 和 onerror事件 ,對于IE5~8還多了一個 onreadystatechange事件 和與之相關的 readyState屬性
onload事件 ,當資源加載完成后觸發(注意:即使資源類型與LINK元素的type屬性值不符,只要資源加載完成就會觸發onload事件)。
onerror事件 ,當找不到資源時會觸發(注意:IE5~11無論任何情況均不會觸發該事件)
onreadystatechange事件 ,IE5~10下readyState變化就會觸發該事件。
readyState屬性 ,用于表示LINK元素當前的資源裝載狀態,默認值為"uninitialized",資源加載中為"loading",資源加載完成為"complete"(注意:資源加載完成不代表資源被成功加載)
本次實驗將創建 LINK元素 并對其的 href屬性 分別賦予以下內容 test.css 、 fsjohnhuang.png 、 :0 、 空字符串 、 空白字符串 、 //:0 、 javascript:void 0 和 data:image/png,foo 。并訂閱img元素的onload和onerror事件,IE5~10下還訂閱了onreadystatechange事件,統計整理其在IE5~11、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) |
不會觸發網絡請求 |
從表格數據得到以下規律:
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觸發一次。
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事件。
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事件。
若有紕漏請各位指正,謝謝!
尊重原創,轉載請注明來自:http://www.cnblogs.com/fsjohnhuang/p/4149793.html ^_^肥子John
http://www.w3help.org/zh-cn/causes/BX9021
http://www.w3school.com.cn/tags/tag_link.asp
文章列表