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

回顧下前面的介紹,浏覽器模式決定: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,如需轉載請自行聯系原作者