IE (第一部分) 浏览器 中 关于浏览器模式和文本模式的困惑
什么是浏览器模式和文本模式?
经常使用IE开发者工具的同学,肯定见过浏览器模式和文本模式,对于这两个名词,综合相关文档解释如下:
浏览器模式(Browser Mode),用于切换IE针对该网页的默认文本模式、对不同版本浏览器的条件注释解析、决定请求头里userAgent的值。它在浏览器发出请求之前就已经确定,网站没有办法修改这个值。它代表的是用户以何种浏览器访问网站。IE9支持下列浏览器模式:
(IE9兼容性模式与IE7模式的区别是:前者在UA里加上了Trident版本,后者和IE7完全一致无Trident标识;IE8中,IE9兼容性模式对应为IE8兼容性模式,UA里Trident版本为4.0,其他没变化。另,IE8中没有IE9模式)
文本模式(Document Mode),其实就是经常说的文档模式。不同的文本模式对应不同的排版引擎,不同的JS引擎。上面提到,每一种浏览器模式对应一种默认的文本模式,网站还可以通过一些手段来更改文本模式,它代表的是浏览器以何种模式呈现页面。IE9有下列文本模式:
(需要说明的是,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),X-UA-Compatible确实会将浏览器文本模式改到了IE7标准(根据documentMode和JS引擎)。奇怪的是,文本模式的改变导致了浏览器模式的改变,因为条件注释是由浏览器模式决定的。本例中,文本模式改到IE7标准,条件注释也跟着变成IE7,意味着浏览器模式变到IE9/IE8兼容性(从IE9的测试来看,不能是IE7,因为UA里包含Trident)。至于IE8中JS取到的UA为什么没有变化,可能是bug或者理解不一致。
测试二、那如果把测试地址加到兼容性列表呢?根据前文,这种情况浏览器模式应该是IE9/IE8兼容性,对应的文本模式依然是IE7标准。测试结果如下:
上表是完全符合预期的。
测试三、如果把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们,实在过于奇葩,不在本文范围内。
来源:https://www.imququ.com/post/browser-mode-and-document-mode-in-ie.html
IE (第一部分) 浏览器 中 关于浏览器模式和文本模式的困惑的更多相关文章
- IE (第二部分) 浏览器 中 关于浏览器模式和文本模式
判断真正的 IE 版本 很多 JS 框架都通过 UA 判断 IE 的版本.对于 IE6,这种做法没问题( IE6 没有浏览器模式的概念,也没有其它 IE 可以把浏览器模式改为 IE6:IE7 虽然也没 ...
- IE的浏览器模式、文本模式
最近在部署网页的时候,发现IE下的布局完成混乱. 在改变IE的文本模式后,显示就正常了. IE的浏览器模式,用于切换IE针对该网页的默认文本模式.对不同版本浏览器的条件注释解析.决定请求头里userA ...
- Windows 配置Apache以便在浏览器中运行Python script的CGI模式
打开httpd.conf,找到”#ScriptInterpreterSource Registry “,移除前面的注释# (如果找不到这行,就自己添加进去) 找到“Options Indexes Fo ...
- IE8"开发人员工具"使用详解下(浏览器模式、文本模式、JavaScript调试、探查器)
来源: http://www.cnblogs.com/JustinYoung/archive/2009/04/03/kaifarenyuangongju2.html 在上一篇文章IE8“开发人员工具” ...
- Linux的图形模式和文本模式以及单用户模式切换
1.默认开机进入文本模式 如果想让开机自动进纯文本模式, 修改/etc/inittab 找到其中的 id:5:initdefault: 这行指示启动时的运行级是5,也就是图形模式 改成3就是文本模式了 ...
- 浏览器中的user-agent的几种模式
服务器一般会根据访问的浏览器进行识别,针对不同浏览器才用不同的网站样式及结构,也是通过这个信息判断用户使用的平台模式(手机,pc或平板) 识别为手机一般有这几个关键字: "Windows P ...
- 在浏览器中输入Google.com并且按下回车之后发生了什么(转载)
原文地址:https://github.com/skyline75489/what-happens-when-zh_CN#id9 本文试图回答一个古老的面试问题:当你在浏览器中输入google.com ...
- JS魔法堂:浏览器模式和文档模式怎么玩?
一.前言 从IE8开始引入了文档兼容模式的概念,作为开发人员的我们可以在开发人员工具中通过“浏览器模式”和“文档模式”(IE11开始改为“浏览器模式”改成更贴切的“用户代理字符串”)品味一番,它的出现 ...
- 第十一章:WEB浏览器中的javascript
客户端javascript涵盖在本系列的第二部分第10章,主要讲解javascript是如何在web浏览器中实现的,这些章节介绍了大量的脚本宿主对象,这些对象可以表示浏览器窗口.文档树的内容.这些章节 ...
随机推荐
- Django中常用命令
Django 基本命令 熟练使用Django常用命令能让你事半功倍!!!! 1. 新建一个 django project django-admin.py startproject project-na ...
- 初级安全入门——SQL注入的原理与利用
工具简介 SQLMAP: 一个开放源码的渗透测试工具,它可以自动探测和利用SQL注入漏洞来接管数据库服务器.它配备了一个强大的探测引擎,为最终渗透测试人员提供很多强大的功能,可以拖库,可以访问底层的文 ...
- 制作本地yum源
镜像源是centos当中下载相关软件的地址,我们可以通过制作我们自己的镜像源指定我们去哪里下载impala的rpm包,这里我们使用httpd这个软件来作为服务端,启动httpd的服务来作为我们镜像源的 ...
- 《算法》第六章部分程序 part 5
▶ 书中第六章部分程序,包括在加上自己补充的代码,网络最大流 Ford - Fulkerson 算法,以及用到的流量边类和剩余流量网络类 ● 网络最大流 Ford - Fulkerson 算法 pac ...
- 下载,和scp上传问题
下载,和scp上传问题 wget http://download.openx.org/openx-2.8.10.zip [默认当前目录] scp ldm@192.168.1.150:/var/www ...
- tensorflow实战系列(一)
最近开始整理一下tensorflow,准备出一个tensorflow实战系列,以飨读者. 学习一个深度学习框架,一般遵循这样的思路:数据如何读取,如如何从图片和标签数据中读出成tensorflow可以 ...
- php实现单点登录实例
1.准备两个虚拟域名 127.0.0.1 www.a.com127.0.0.1 www.b.com 2.在a的根目录下创建以下文件 1 //index.php 2 3 <?php 4 sessi ...
- VC编译错误,把类误认为是函数
这段代码是在一个动态库中,我像把这个类导出,于是加上 SC_EXPORTS 宏.class SC_EXPORTS CProtocolCheck{public: CProtocolCheck(void) ...
- day11-mysql中的mysql数据库不见了
mysql中的mysql数据库不见了 昨天刚刚在vmware虚拟机的linux上安装mysql,今天登上就发现一个问题.通过网上漫长的寻找,终于解决了.所以我在这把我解决的步骤跟大家分享一下. 问题就 ...
- day03-数据类型
数据类型 一.介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 mysql常用数据类型概括:#1. 数字: 整型:tinyint.int.bi ...