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

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

经常使用IE开发者工具的同学,肯定见过浏览器模式和文本模式,对于这两个名词,综合相关文档解释如下:

浏览器模式(Browser Mode),用于切换IE针对该网页的默认文本模式、对不同版本浏览器的条件注释解析、决定请求头里userAgent的值。它在浏览器发出请求之前就已经确定,网站没有办法修改这个值。它代表的是用户以何种浏览器访问网站。IE9支持下列浏览器模式:

 userAgent默认文本模式
IE7MSIE 7.0IE7标准
IE8MSIE 8.0 && Trident/4.0IE8标准
IE9MSIE 9.0 && Trident/5.0IE9标准
IE9兼容性MSIE 7.0 && Trident/5.0IE7标准

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),但开发者工具是无法选择近似标准模式的,实际上我们一般都选择触发完全标准模式)

浏览器模式和文本模式有什么用?

用来解决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测试这个页面:

 请求头UAnavigator.userAgent条件注释documentModeJS引擎
IE8MSIE 8.0 && Trident/4.0MSIE 8.0 && Trident/4.0IE77IE7
IE9MSIE 9.0 && Trident/5.0MSIE 7.0 && Trident/5.0IE77IE7

上表说明,浏览器发送请求时的浏览器模式符合预期(根据请求头UA),X-UA-Compatible确实会将浏览器文本模式改到了IE7标准(根据documentMode和JS引擎)。奇怪的是,文本模式的改变导致了浏览器模式的改变,因为条件注释是由浏览器模式决定的。本例中,文本模式改到IE7标准,条件注释也跟着变成IE7,意味着浏览器模式变到IE9/IE8兼容性(从IE9的测试来看,不能是IE7,因为UA里包含Trident)。至于IE8中JS取到的UA为什么没有变化,可能是bug或者理解不一致。

测试二、那如果把测试地址加到兼容性列表呢?根据前文,这种情况浏览器模式应该是IE9/IE8兼容性,对应的文本模式依然是IE7标准。测试结果如下:

 请求头UAnavigator.userAgent条件注释documentModeJS引擎
IE8MSIE 7.0 && Trident/4.0MSIE 7.0 && Trident/4.0IE77IE7
IE9MSIE 7.0 && Trident/5.0MSIE 7.0 && Trident/5.0IE77IE7

上表是完全符合预期的。

测试三、如果把X-UA-Compatible改成IE=edge,继续使用兼容性模式测试呢?结论如下:

 请求头UAnavigator.userAgent条件注释documentModeJS引擎
IE8MSIE 7.0 && Trident/4.0MSIE 7.0 && Trident/4.0IE88IE8
IE9MSIE 7.0 && Trident/5.0MSIE 9.0 && Trident/5.0IE99IE9

这个结论其实跟测试一是一致的: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们,实在过于奇葩,不在本文范围内。

参考:

  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

 

原文链接:http://www.imququ.com/post/browser-mode-and-document-mode-in-ie.html

 

 

转载于:https://www.cnblogs.com/hustskyking/archive/2013/06/08/browser-mode-and-doccument-mode.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/433472.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 关联索引_mysql中关于关联索引的问题——对a,b,c三个字段建立联合索引,那么查询时使用其中的2个作为查询条件,是否还会走索引?...

情况描述&#xff1a;在MySQL的user表中&#xff0c;对a,b,c三个字段建立联合索引&#xff0c;那么查询时使用其中的2个作为查询条件&#xff0c;是否还会走索引&#xff1f;根据查询字段的位置不同来决定&#xff0c;如查询a, a,b a,b,c a,c 都可以走索引的&#…

A20 看门狗

前言 说到看门狗&#xff0c;应该不会陌生&#xff0c;看门狗说白了就是一个定时器&#xff0c;但是它有一个非常重要的功能就是复位系统。在A20里&#xff0c;看门狗的操作非常简单&#xff0c;只有两个寄存器&#xff0c;不需要操作时钟相关的东西&#xff0c;系统起来后可以…

python拼接大量ts文件_Python爬取.ts文件,合并为mp4

目标&#xff1a;爬影视网站ts文件到本地&#xff0c;合并成mp4文件下载ts文件本着不重复造轮子的精神(好吧其实是我懒)&#xff0c;想用迅雷批量下载爬取&#xff0c;但是迅雷提供的通配符过于简单无法构造URL&#xff0c;只能自己写脚本如下&#xff1a;# -*- coding: utf-8 …

android学习笔记之ProgressDialog的使用

在很多PC软件或手机软件中&#xff0c;我们都会看见 “加载中...” 类似的对话框&#xff0c;当然&#xff0c;在android应用程序中也是如此。如果我们想在android应用程序中使用这样的效果&#xff0c;那么就需要用到ProgressDialog。首先&#xff0c;我们来看一下ProgressDia…

asterisk 互联问题

asterisk A 和asterisk B互联。 A下面有账户1001&#xff0c;B下面有账户2001 当1001呼叫2001时&#xff0c;B的sip.conf里不能有1001。 当2001呼叫1001时&#xff0c;A的sip.conf里不能有2001。 否则&#xff0c;呼叫无法呼叫成功。 下面为截图 实际和在振铃时&#xff0…

清除python shell中的内容_如何使用python脚本定时清空文件内容?

我们一直在对大家强调关于python脚本的使用&#xff0c;但是有部分同学提出疑问&#xff0c;就是关于上期跟大家说的shell脚本没有实质性的使用效果&#xff0c;如果在实际应用里&#xff0c;要怎么使用这个脚本&#xff0c;它又能实现什么效果&#xff0c;其实针对这个内容&am…

ACCESS中不支持left join解决方案

今天在做基于 access数据库项目中,做外连接时,发现Access不支持两个以上的 left join 在网上查一下,有哥们说每个 left join 要加 () 在修改之前(不能执行,ms sql 里执行以通过) select table1.fildes1, table1.fildes2,table2.fildes1, table2.fildes2,table3.fildes…

docker mysql主从_使用docker 实现MySQL主从同步/读写分离

1. 利用 docker 实现 mysql 主从同步 / 读写分离为了保证数据的完整和安全&#xff0c;mysql 设计了主从同步&#xff0c;一个挂掉还可以用另个。最近重构论坛&#xff0c;想来改成主从吧。担心失误&#xff0c;就先拿 docker 练练手。通过本文实际你会操作到。mysql 的主从同步…

Linux中的EAGAIN含义

在Linux环境下开发经常会碰到很多错误(设置errno)&#xff0c;其中EAGAIN是其中比较常见的一个错误(比如用在非阻塞操作中)。从字面上来看&#xff0c;是提示再试一次。这个错误经常出现在当应用程序进行一些非阻塞(non-blocking)操作(对文件或socket)的时候。例如&#xff0c;…

mysql sys 数据库_mysql sys 数据库

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

python get方法请求参数_如何解决TypeError get()在使用get方法的Python请求中恰好接受2个参数(给定3个)...

在Python中使用Request对象时出现错误.下面是我的代码.class APIDOC(Document):def request_api(self):method_type self.method_typeapi self.apiparameters self.parameterssession_object requests.session()self.get_login(session_object)if method_type "POST&…

getsockname与getpeername

getsockname与getpeername是返回套接口关联的本地协议地址和远程协议地址。 int getsockname(int sockfd, struct sockaddr * localaddr, socken_t * addrlen); int getpeername(int sockfd, struct sockaddr * peeraddr, socken_t * addrlen); 返回0表示成功&#xff0c;返回1…

KingPaper初探ThinkPHP3.1.2之目录部署(二)

在我们使用Thinkphp搭建项目时&#xff0c;目录部署是必不可少的一个环节接下来我们来学习以下目录部署在APP目录下面现在项目目录下所拥有的文件 ThinkPHP目录 存放thinkphp框架系统目录Home 我们创建的应用目录index.php我们的入口文件 我们还需要创建Public 网站所有的公共…

mysql函数match_Mysql全文搜索match…against的用法 | 学步园

全文检索在 MySQL 中就是一个 FULLTEXT 类型索引。FULLTEXT索引用于 MyISAM 表&#xff0c;可以在 CREATE TABLE 时或之后使用 ALTER TABLE 或 CREATE INDEX 在CHAR、 VARCHAR 或 TEXT 列上创建。对于大的数据库&#xff0c;将数据装载到一个没有 FULLTEXT 索引的表中&#x…

华为手机可以安装python吗_何安装python2.6

由于机器上的python 版本比较高&#xff0c;需要安装一个低版本的python具体执行步骤&#xff1a;1. 使用如下命令下载到2.6版本wget http://www.python.org/ftp/python/2.6/Python-2.6.tgz2. 解压pythontar xzf Python-2.6.tgzcd Python-2.63. 编译安装python./configure --pr…

Linux串口编程

.串口概述 常见数据通信方式:并行通信&#xff0c;串行通信 UART的主要操作&#xff1a; >数据发送及接受 >产生中断 >产生波特率 >Loopback模式 >红外模式 >自动流控模式 串口参数的配置主要包括:波特率、数据位、停止位、流控协议…

[转]如何在.NET MVC中使用jQuery并返回JSON数据

本文转自&#xff1a;http://blog.sina.com.cn/s/blog_48e42dc90100xp1p.html 二、开始实践 - jQuery端 假设我们要从服务器端获取一个文章列表&#xff0c;并把文章条目显示在页面中&#xff0c;而加载的过程要用ajax实现&#xff0c;即实现异步加载。那么我们先来完成jquery向…

mysql查当前用户的的命令_mysql命令大全用户管理相关命令

grant 普通数据用户&#xff0c;查询、插入、更新、删除 数据库中所有表数据的权利。grant select on testdb.* to common_user’%’grant insert on testdb.* to common_user’%’grant update on testdb.* to common_user’%’grant delete on testdb.* to common_user’%’或…

ud分区删除工具_硬盘分区GPT分区怎么转MBR呢?硬盘分区GPT分区转MBR教程

很多用户的电脑预装的是win10系统&#xff0c;想要重装成win7系统。不过新电脑一般都是GPT分区&#xff0c;想要把win10重装成win7&#xff0c;首先需要将GPT分区转MBR。那么&#xff0c;硬盘分区GPT分区怎么转MBR呢?下面就让小编为大家带来硬盘分区GPT分区转MBR教程。提示:单…

串口

1. 5350串口可以设置阻塞模式&#xff0c;3352只能是非阻塞模式 2. termios结构体为全局变量或局部变量&#xff0c;5350分别为阻塞或非阻塞 3. termios结构体在使用前必须清0&#xff0c;否则会出现有时收不到数据的情况 4. termios结构体必须被设置&#xff0c;否则会出现发送…