關於瀏覽器模式和文本模式的困惑

什麼是瀏覽器模式和文本模式?

常用IE開發者工具的同窗,確定見過瀏覽器模式和文本模式,對於這兩個名詞,綜合相關文檔解釋以下: html

瀏覽器模式(Browser Mode),用於切換IE針對該網頁的默認文本模式、對不一樣版本瀏覽器的條件註釋解析、決定請求頭裏userAgent的值。它在瀏覽器發出請求以前就已經肯定,網站沒有辦法修改這個值。它表明的是用戶以何種瀏覽器訪問網站。IE9支持下列瀏覽器模式: web

  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),但開發者工具是沒法選擇近似標準模式的,實際上咱們通常都選擇觸發徹底標準模式) ide

瀏覽器模式和文本模式有什麼用?

用來解決IE各版本帶來的兼容性問題。根據微軟描述的IE兼容性策略,在IE8+訪問一個頁面要通過這樣的流程: 工具

1、首先,瀏覽器要肯定瀏覽器模式。上面說過,瀏覽器模式是在請求發送以前就必須肯定,默認取最新(IE9爲IE9標準,IE8爲IE8標準),有兩種方式能夠更改它: 測試

  • 經過開發者工具選擇(可選項見上表);
  • 經過點擊兼容性視圖按鈕;
  • 命中兼容性視圖列表(微軟維護的須要採用兼容性視圖的列表。IE8+默認對這個列表和局域網的網址都會採用相應的兼容性模式);

2、瀏覽器經過請求頭裏userAgent的值,告訴服務器當前是何種瀏覽器模式; 網站

3、服務器能夠經過下面方式改變瀏覽器文本模式: ui

  • doctype;
  • X-UA-Compatible Meta或對應的響應頭;

4、瀏覽器綜合考慮開發者工具設置、第三步服務器返回的設置、兼容性列表設置等等狀況,決定頁面使用何種文本模式。這個過程有點複雜,放一張Qwrap羣裏灰大提供的流程圖,能夠本身點開看大圖。 spa

(上圖是IE9選取文本模式的流程圖,這裏還有IE8版本,有一些區別)

問題終於來了!

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

測試1、根據前文,若是用戶瀏覽器沒有激活兼容性視圖;沒有開啓IE開發者工具。那麼IE9的瀏覽器模式默認爲IE9,默認對應的文本模式應該是IE9標準(對於IE8來講,是相似的),咱們經過下列代碼將它改到IE7標準

<meta http-equiv="X-UA-Compatible" content="IE=7">

下面,咱們分別用原生IE八、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或者理解不一致。

測試2、那若是把測試地址加到兼容性列表呢?根據前文,這種狀況瀏覽器模式應該是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

上表是徹底符合預期的。

測試3、若是把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不變。

測試4、那若是經過開發者工具人爲設置瀏覽器模式和文本模式呢?通過測試,這樣測試都是符合預期的。例如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們,實在過於奇葩,不在本文範圍內。

參考:

  1. Testing sites with Browser Mode vs. Doc Mode
  2. X-UA-Compatible header/meta tag is NOT the same as the Internet Explorer 8+ Compatibility View button
相關文章
相關標籤/搜索