網上的一篇文章:http://blog.csdn.net/lnn2007/article/details/7747344
什么是瀏覽器模式和文本模式?
經常使用IE開發者工具的同學,肯定見過瀏覽器模式和文本模式,對於這兩個名詞,綜合相關文檔解釋如下:
瀏覽器模式(Browser Mode),用於切換IE針對該網頁的默認文本模式、對不同版本瀏覽器的條件注釋解析、決定請求頭里userAgent的值。它在瀏覽器發出請求之前就已經確定,網站沒有辦法修改這個值。它代表的是用戶以何種瀏覽器訪問網站。IE9支持下列瀏覽器模式:
userAgent | 默認文本模式 | |
---|---|---|
IE7 | MSIE 7.0 | IE7標准 |
IE8 | MSIE 8.0 && Trident/4.0 | IE8標准 |
IE9 | MSIE 9.0 && Trident/5.0 | IE9標准 |
IE9兼容性 | MSIE 7.0 && Trident/5.0 | IE7標准 |
(IE9兼容性模式與IE7模式的區別是:前者在UA里加上了Trident版本,后者和IE7完全一致無Trident標識;IE8中,IE9兼容性模式對應為IE8兼容性模式,UA里Trident版本為4.0,其他沒變化。另,IE8中沒有IE9模式)
文本模式(Document Mode),其實就是經常說的文檔模式。不同的文本模式對應不同的排版引擎,不同的JS引擎。上面提到,每一種瀏覽器模式對應一種默認的文本模式,網站還可以通過一些手段來更改文本模式,它代表的是瀏覽器以何種模式呈現頁面。IE9有下列文本模式:
documentMode | |
---|---|
IE7標准 | 7 |
IE8標准 | 8 |
IE9標准 | 9 |
怪異(Quirks) | 5 |
(需要說明的是,IE8開始支持的渲染機制有:怪異模式(quirks mode)、完全標准模式(standards mode)和近似標准模式(almost standards mode),但開發者工具是無法選擇近似標准模式的,實際上我們一般都選擇觸發完全標准模式)
瀏覽器模式和文本模式有什么用?
用來解決IE各版本帶來的兼容性問題。根據微軟描述的IE兼容性策略,在IE8+訪問一個頁面要經過這樣的流程:
一、首先,瀏覽器要確定瀏覽器模式。上面說過,瀏覽器模式是在請求發送之前就必須確定,默認取最新(IE9為IE9標准,IE8為IE8標准),有兩種方式可以更改它:
- 通過開發者工具選擇(可選項見上表);
- 通過點擊兼容性視圖按鈕;
- 命中兼容性視圖列表(微軟維護的需要采用兼容性視圖的列表。IE8+默認對這個列表和局域網的網址都會采用相應的兼容性模式);
二、瀏覽器通過請求頭里userAgent的值,告訴服務器當前是何種瀏覽器模式;
三、服務器可以通過下面方式改變瀏覽器文本模式:
- doctype;
- X-UA-Compatible Meta或對應的響應頭;
四、瀏覽器綜合考慮開發者工具設置、第三步服務器返回的設置、兼容性列表設置等等情況,決定頁面使用何種文本模式。這個過程有點復雜,放一張Qwrap群里灰大提供的流程圖,可以自己點開看大圖。
(上圖是IE9選取文本模式的流程圖,這里還有IE8版本,有一些區別)
問題終於來了!
回顧下前面的介紹,瀏覽器模式決定:1)發送給服務端的UA;2)默認的文本模式;3)如何解析條件注釋。它在請求發送前就已經確定,且不受服務端控制。文本模式決定:1)排版引擎;2)JS引擎。它在瀏覽器得到響應后最終確定,服務端可通過doctype或X-UA-Compatible來控制。
測試一、根據前文,如果用戶瀏覽器沒有激活兼容性視圖;沒有開啟IE開發者工具。那么IE9的瀏覽器模式默認為IE9,默認對應的文本模式應該是IE9標准(對於IE8來說,是類似的),我們通過下列代碼將它改到IE7標准:
<
meta
http-equiv
=
"X-UA-Compatible"
content
=
"IE=7"
>
|
下面,我們分別用原生IE8、IE9測試這個頁面:
請求頭UA | navigator.userAgent | 條件注釋 | documentMode | JS引擎 | |
---|---|---|---|---|---|
IE8 | MSIE 8.0 && Trident/4.0 | MSIE 8.0 && Trident/4.0 | IE7 | 7 | IE7 |
IE9 | MSIE 9.0 && Trident/5.0 | MSIE 7.0 && Trident/5.0 | IE7 | 7 | IE7 |
上表說明,瀏覽器發送請求時的瀏覽器模式符合預期(根據請求頭UA),X-UA-Compatible確實會將瀏覽器文本模式改到了IE7標准(根據documentMode和JS引擎)。奇怪的是,文本模式的改變導致了瀏覽器模式的改變,因為條件注釋是由瀏覽器模式決定的。本例中,文本模式改到IE7標准,條件注釋也跟着變成IE7,意味着瀏覽器模式變到IE9/IE8兼容性(從IE9的測試來看,不能是IE7,因為UA里包含Trident)。至於IE8中JS取到的UA為什么沒有變化,可能是bug或者理解不一致。
測試二、那如果把測試地址加到兼容性列表呢?根據前文,這種情況瀏覽器模式應該是IE9/IE8兼容性,對應的文本模式依然是IE7標准。測試結果如下:
請求頭UA | navigator.userAgent | 條件注釋 | documentMode | JS引擎 | |
---|---|---|---|---|---|
IE8 | MSIE 7.0 && Trident/4.0 | MSIE 7.0 && Trident/4.0 | IE7 | 7 | IE7 |
IE9 | MSIE 7.0 && Trident/5.0 | MSIE 7.0 && Trident/5.0 | IE7 | 7 | IE7 |
上表是完全符合預期的。
測試三、如果把X-UA-Compatible改成IE=edge,繼續使用兼容性模式測試呢?結論如下:
請求頭UA | navigator.userAgent | 條件注釋 | documentMode | JS引擎 | |
---|---|---|---|---|---|
IE8 | MSIE 7.0 && Trident/4.0 | MSIE 7.0 && Trident/4.0 | IE8 | 8 | IE8 |
IE9 | MSIE 7.0 && Trident/5.0 | MSIE 9.0 && Trident/5.0 | IE9 | 9 | IE9 |
這個結論其實跟測試一是一致的:X-UA-Compatible為IE=edge,意味着文本模式會使用最新可用的版本,然而文本模式的更改,又把瀏覽器模式從IE9/IE8兼容性變成IE9/IE8。IE9會按照新的瀏覽器模式來設置JS的navigator.userAgent,IE8下JS的UA不變。
測試四、那如果通過開發者工具人為設置瀏覽器模式和文本模式呢?經過測試,這樣測試都是符合預期的。例如IE9下,設置瀏覽器模式為IE8,文本模式為IE7標准,請求頭UA、JS的UA、條件注釋都表明瀏覽器模式是IE8,documentMode和JS引擎都表明文本模式是IE7標准。因為,IE開發者工具的優先級最高,設置了這個,其他條件統統無視!
結論
IE8/9中X-UA-Compatible對文本模式的改變會導致瀏覽器模式的改變,也就是說服務端可以間接控制瀏覽器模式。這與微軟文檔里這一段描述有出入:
An important detail to remember is that Browser Mode is chosen before IE requests web content. This means that sites cannot choose a Browser Mode.
對於IE8,如果網站通過X-UA-Compatible meta/header更改文本模式為當前瀏覽器模式默認文本模式之外的值,那么頁面將按照新的文本模式來呈現,條件注釋也按照新的文本模式對應的瀏覽器模式來解析,但是JS獲取的UA是瀏覽器模式初始狀態。這樣會導致用JS獲取UA得到的瀏覽器版本,與實際渲染的瀏覽器版本不符,這會對基於UA的瀏覽器檢測造成干擾。
對於IE9,只有一點與IE8不同:JS獲取到的是新文本模式對應的瀏覽器模式的UA。這會導致用JS獲取UA得到的瀏覽器版本,與請求頭發送給服務器UA里標識的瀏覽器版本不符,這可能對統計有影響。
對於IE這種兼容性方案,幾乎不可能做到理論上的完美。個人感覺還是IE9的策略影響面較小,更好一些。
PS,上述結論都是我用Windows XP的原生IE8,Windows 7的原生IE9親自測試得出來的。對於國內那些IE Shell們,實在過於奇葩,不在本文范圍內。
參考:
- Testing sites with Browser Mode vs. Doc Mode
- X-UA-Compatible header/meta tag is NOT the same as the Internet Explorer 8+ Compatibility View button
本文鏈接:http://www.imququ.com/post/browser-mode-and-document-mode-in-ie.html