浏览器模式与文本模式

转自:http://yiminghe.iteye.com/blog/802021


IE 版本实在太多了,而且每个版本又变化很大,出到 IE9 连微软都开始担心开发者能否搞定,于是就有了这篇官方博文,详细介绍了自 IE8 起引入的兼容性解决方案:


Testing sites with Browser Mode vs. Doc Mode


浏览器模式

 


不受程序员控制,用户可以自由选择合适的ie版本,影响了以下三个方面:


1.发送给服务器合适的UA

2.控制页面中的条件注释 。(条件注释依赖于 UA 串) 

3.对应了默认的文本模式(渲染模式,IE8 引入document.Mode)。


关于默认对应关系可见:

 



updated 2010-10-24

 

ie UA 判断需要考虑渲染引擎版本 trident

 

兼容模式和其他模式的区别在于,兼容模式会在UA中表示自己是 MSie7 但是同时也会表示自己的渲染引擎是trident 5.0,如下:

 

Js代码    收藏代码
  1. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)  

 

但是选择ie7模式时,则会完全丢弃掉trident版本:

 

Js代码    收藏代码
  1. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)  
 

一般来说,终端用户可选择兼容模式(地址栏兼容按钮),但是开发者通过 trident 仍然可以知道真正的浏览器版本,其他模式主要用于程序员调试(程序完全不知),终端用户如果选择后果自负!


比如一个 ie9 问题,当程序设置 document mode 处于 ie9 时,透明度 filter 设置会失效即透明失效,即使设置了opacity,这是就可以根据trident来判断,无论是 MSIE7.0 (兼容模式)还是 MSIE9.0(ie9模式) [具体哪种模式受微软白名单控制以及用户选择],都把filter去掉,具体方法则是初始化时在页面body上加入class:tridentxx,在样式中写明:

 

Html代码    收藏代码
  1. <body class='trident5'>  
  2.   
  3. .trident5 xx{  
  4.   filter:none;  
  5. }  
 

 

文本模式

 


直接和界面显示相关,用来指示选择具体的渲染引擎,例如 ie8 标准模式下不支持 css表达式。脚本可以通过 document.documentMode  探测。


updated 2010-11-10 

 

当切换 document.documentMode ,不仅会切换渲染引擎,而且会切换 js 引擎,可在切换前后分别执行以下程序测试:

 

Js代码    收藏代码
  1. typeof Object.create  

 

 

 


可以通过以下方面由程序员控制


1. 页面中的 DOCTYPE 属性。


需要注意的是:实际上从 ie8 起存在 3 种渲染机制,目前推荐 <!DOCTYPE html>触发完全标准模式。

其他详见:Quirks mode、Almost standards mode、Standards mode


2. X-UA-Compatible Meta tag


可以在 head 开头 插入 meta 标签:

 

Html代码    收藏代码
  1. <meta http-equiv="X-UA-Compatible" content="IE=mode" >  

 

mode 取值结合 1 DOCTYPE 会直接影响到使用哪个渲染引擎:

 


更详细的见这里:how-ie8-determines-document-mode

 

3. HTTP Header


同2,不过直接操作 http 协议头,需要注意的是 2 的优先级比 3 高。



最后 如果还不能够确定,那么 ie 的兼容性列表 也会影响到具体表现,可在

res://iecompat.dll/iecompatdata.xml

查看,用户也可在 工具-兼容性视图设置 下手动设置,将特定网站加入兼容性列表。

 


update 2010-11-17 :

 

attribute 与 property , content value 与 dom value

 

attribute 的判断读取 在 ie <9 之前是非常混乱的事情,节点的 .attributes 在标准浏览器下只会返回用户设置的属性节点集合,而在 ie<8 下则会把所有可以设置的属性都返回过来,特别在需要知道某个元素是否被用户设置了属性时就会十分麻烦,需要遍历.attributes 一一判断 specified 是否为 true ,而 documentMode 也会切换 js 引擎,在 ie8 的文本模式选择了 ie7 标准时,其属性方面和真实的 ie7 表现一致,那么这时为了鲁棒性需要这样判断:

 

Js代码    收藏代码
  1. //直接判断引擎,防止兼容性模式影响  
  2. var ieEngine=(function() {  
  3.      if (!UA.ie) return;  
  4.      return document.documentMode || UA.ie;  
  5. })();  
  6.   
  7. var hasAttributes = ieEngine < 8 ?  
  8. function (el) {  
  9.     var attributes = el.attributes;  
  10.     for (var i = 0; i < attributes.length; i++) {  
  11.         var attribute = attributes[i];  
  12.         if (attribute.specified) {  
  13.             return true;  
  14.         }  
  15.     }  
  16.     return false;  
  17. } : function (el) {  
  18.     //删除firefox自己添加的标志  
  19.     UA.gecko && el.removeAttribute("_moz_dirty");  
  20.     return el.hasAttributes();  
  21. }  
 

关于 attribute 与 property 的关系就更复杂了,在 ie6,7 下表示 content value 的attribute 与表示 dom value 的 property 混淆了,并且在 ie8 documentMode 为混杂以及 ie7 模式下和 ie6,7 保持一致,如下:

 

Html代码    收藏代码
  1. <a href='../x.html' id='t'>test</a>  
  2. <script>  
  3. var a=document.getElementById("t");  
  4. alert(a.getAttribute("href"));  
  5. alert(a.getAttribute("href",2));  
  6. </script>  


另一点需要注意的是,设置 innerHTML 在 ie6,7 下会触发设置的 content value 转换成为dom value,当然这只对 html 相关属性起作用,只有 html 属性才可能有不同于 content value 的 dom value。如下:

 

Java代码    收藏代码
  1. <div id='tt'>  
  2. <a href='../x.html' id='t' _saved_href='../x.html'>test</a>  
  3. </div>  
  4. <script>  
  5. var tt=document.getElementById("tt");  
  6. alert(tt.innerHTML);  
  7. tt.innerHTML=tt.innerHTML;  
  8. alert(tt.innerHTML);  
  9. </script>  

 

 

单个属性节点存在判断:

 

在 ie 下可用:

 

Js代码    收藏代码
  1. elem.attributes[name] && elem.attributes[name].specified  
 

但是对于多个单词组成的属性,例如 tabindex 会出问题,最好用

 

Js代码    收藏代码
  1. var name='tabindex';  
  2. elem.tabIndex=1;  
  3. var attr = elem.getAttributeNode(name);  
  4. return attr ? attr.specified : false;  

 

来判断。

 

而对于 attribute 和 property 还没有完全分开,如果设置自定义属性/expando,那么会发现无论读 expando 还是 attribute 都可以读出来 :(

 

Js代码    收藏代码
  1. var o=document.body;  
  2. o.xx="oo";  
  3. o.setAttribute("xx2","oo2");  
  4. alert(o.xx);  
  5. alert(o.getAttribute("xx"));  
  6. alert(o.xx2);  
  7. alert(o.getAttribute("xx2"));  
 

 

ie9 则是完全解决了

 

 

具体可见:









 

 

PS: 这个工 具也不错 


Introducing the IE8 Developer Tools JScript Profiler

 


其他文章:


IE’s Compatibility Features for Site Developers

 

Beyond DOCTYPE: Web Standards, Forward Compatibility, and IE8

 

Internet Explorer 8 document and browser modes


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值