关于浏览器模式和文本模式的困惑

什么是浏览器模式和文本模式?

常用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
相关文章
相关标签/搜索