天天看點

IE 的浏覽器模式和文本模式(一)

經常使用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

(IE9相容性模式與IE7模式的差別是:前者在UA裡加上了Trident版本,後者和IE7完全一緻無Trident辨別;IE8中,IE9相容性模式對應為IE8相容性模式,UA裡Trident版本為4.0,其他沒變化。另,IE8中沒有IE9模式)

文本模式(Document Mode),其實就是經常說的文檔模式。不同的文本模式對應不同的排版引擎,不同的JS引擎。上面提到,每一種浏覽器模式對應一種預設的文本模式,網站還可以通過一些手段來更改文本模式,它代表的是浏覽器以何種模式呈現頁面。IE9有下列文本模式:

文本模式

documentMode

7

8

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群裡灰大提供的流程圖,可以自己點開看大圖。

IE 的浏覽器模式和文本模式(一)

回顧下前面的介紹,浏覽器模式決定:1)發送給服務端的UA;2)預設的文本模式;3)如何解析條件注釋。它在請求發送前就已經确定,且不受服務端控制。文本模式決定:1)排版引擎;2)JS引擎。它在浏覽器得到響應後最終确定,服務端可通過doctype或X-UA-Compatible來控制。

測試一、根據前文,如果使用者浏覽器沒有激活相容性視圖;沒有開啟IE開發者工具。那麼IE9的浏覽器模式預設為IE9,預設對應的文本模式應該是IE9标準(對于IE8來說,是類似的),我們通過下列代碼将它改到IE7标準:

請求頭UA

navigator.userAgent

條件注釋

JS引擎

上表說明,浏覽器發送請求時的浏覽器模式符合預期(根據請求頭UA),X-UA-Compatible确實會将浏覽器文本模式改到了IE7标準(根據documentMode和JS引擎)。奇怪的是,文本模式的改變導緻了浏覽器模式的改變,因為條件注釋是由浏覽器模式決定的。本例中,文本模式改到IE7标準,條件注釋也跟着變成IE7,意味着浏覽器模式變到IE9/IE8相容性(從IE9的測試來看,不能是IE7,因為UA裡包含Trident)。至于IE8中JS取到的UA為什麼沒有變化,可能是bug或者了解不一緻。

測試二、那如果把測試位址加到相容性清單呢?根據前文,這種情況浏覽器模式應該是IE9/IE8相容性,對應的文本模式依然是IE7标準。測試結果如下:

MSIE 7.0 && Trident/4.0

上表是完全符合預期的。

測試三、如果把X-UA-Compatible改成IE=edge,繼續使用相容性模式測試呢?結論如下:

這個結論其實跟測試一是一緻的: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們,實在過于奇葩,不在本文範圍内。

本文轉自 h2appy  51CTO部落格,原文連結:http://blog.51cto.com/h2appy/1852350,如需轉載請自行聯系原作者

繼續閱讀