文档章节

Javascript浏览器兼容性

wersdffg
 wersdffg
发布于 2015/07/23 17:56
字数 3566
阅读 813
收藏 9

JS <noscript>标签

早期浏览器都面临一个特殊的问题,即当浏览器不支持JavaScript 时如何让页面平稳地退化。对这个问题的最终解决方案就是创造一个<noscript>元素,用以在不支持JavaScript 的浏览器中显示替代的内容。这个元素可以包含能够出现在文档<body>中的任何HTML 元素一一<script>元素除外。

包含在<noscript>元素中的内容只有在下列情况下才会显示出来:
  • 浏览器不支持脚本;
  • 浏览器支持脚本,但脚本被禁用。

符合上述任何一个条件,浏览器都会显示<noscript>中的内容。而在除此之外的其他情况下,浏览器不会呈现<noscript> 中的内容。

请着下面这个简单的例子:
<html>
<head>
<tit1e>Exarnp1e HTML Page</tit1e>
<script type="text/javascript" defer="defer" src="example1. js">< /script>
<script type="text/javascript" defer="defer" src="example2. js">< /script>
</head>
<body>
<noscript><p>本页面需要浏览器支持(启用)JavaScript。</noscript>
</body>
</html>

这个页面会在脚本无效的情况下向用户显示一条消息,而在启用了脚本的浏览器中,用户永远也不会看到它一一尽管它是页面的一部分。

注意:现代浏览器都对JavaScript进行了支持,一般是在用户的浏览器禁用了脚本的情况下才会显示<noscript>的内容。

不推荐使用的嵌入JS脚本的语法

在最早引入<script>元素的时候,该元素与传统HTML的解析规则是有冲突的。由于要对这个元素应用特殊的解析规则,因此在那些不支持JavaScript 的浏览器一一最典型的是Mosaic-一一中就会导致问题。具体来说,不支持JavaScript的浏览帮会把<script>元素的内容直接输出到页面中,因而会破坏页面的布局和外观。

<script><!--function sayHi(){alert ("Hi! " ) ;--></script>


Netscape与Mosaic协商并提出了一个解决方案,让不支持<script>元素的浏览器能够隐藏嵌入的JavaScript 代码。这个方案就是把JavaScript 代码包含在一个HTML 注释中, 像下面这样:
给脚本加上HTML注释后, Mosaic 等浏览器就会忽略<script>标签中的内容,而那些支持JavaScript 的浏览器在遇到这种情况时,则必须进一步确认其中是否包含需要解析的JavaScript 代码。

虽然这种注释JavaScript 代码的格式得到了所有浏览器的认可,也能被正确解释,但由于所有的现代浏览器都已经支持JavaScript ,因此也就没有必要再使用这种格式了。

JS事件(Event)兼容性探究

 

事件(Event)即为用户的动作,例如:用户点击鼠标,产生onclick事件;按下键盘,产生onkeyDown事件;改变输入框的值,产生onchange事件...

W3C标准规定,事件是作为函数的参数传入的,例如:
<p id="demo">点击我将获得屏幕坐标</p>
document.getElementById("demo").onclick=function(e)
{
    alert(e.screenX);
}
当在元素上点击时,弹出警告框,内容为鼠标在屏幕上的横坐标。这里函数传入的参数e,就是事件,浏览器会实时跟踪用户的行为,如e.screenX、e.screenY、e.offsetX、e.offsetY...

这种做法在FireFox、Chrome、Safari等遵循W3C规范的浏览器下是没有问题的,唯独在IE(暂时仅限于8.0以下版本,8.0以上版本笔者未曾测试)下是行不通的,IE采用了一种非标准的方式,并不是将事件作为函数参数传入,而是将事件作为window对象的event属性:window.event、window.event.screenX...

所以,我们在写代码的时候要照顾到IE,做好事件的兼容。

下面是笔者给出的一个简单的兼容示例,该示例并没有去判断浏览器,仅仅使用了一个小技巧。
<p id="demo">点击我将获得屏幕坐标</p>
document.getElementById("demo").onclick=function(e)
{
    var e=e||event;
    alert(e.screenX);
}
注意,不要将var e=e||event; 写成 var e=event||e; ,这在FireFox下会提示错误,FireFox无法处理未声明未赋值的变量event。

这里大家可能有疑虑,为什么是var e=e||event; ,为什么是 或运算(||),这样的结果只能是e=true或者e=false?

笔者告诉大家,在大多数编程语言里,或运算(||)返回的并不只是true或者false,而是返回第一个不为false的变量的值, 例如:
var a=5||6;  //a=5
var b=0||5;  //b=5
var c=false||"www.itxueyuan.com";  //c="www.itxueyuan.com"
var e=e||event;  //e为用户事件

好,这几个例子,笔者相信大家一定明白了,上面对事件兼容的巧妙处理,也就迎刃而解了。

IT学院提醒,大家在处理浏览器兼容问题的时候,尽量不要去判断浏览器,那将会为向后兼容带来风险,或许某个升级的版本开始遵循W3C标准,我们之前写的代码在该版本上就会产生错误,得不到预想结果。

例如,某个升级的IE版本支持将事件作为函数参数传入,抛弃了将事件作为window的属性,而我们的代码,恰恰是这个样子的:
if( (/ie/i).test(navigator.userAgent) )
    document.getElementById("demo").onclick=function()
    {

Javascript addEventListener和attachEvent的区别


        alert(window.event.screenX);
    }
else
    document.getElementById("demo").onclick=function(e)
    {
        alert(e.screenX);
    }
那么在升级的IE浏览器上运行就会产生错误了。

最后,梳理了思路,再把上面的代码重复一遍。
<p id="demo">点击我将获得屏幕坐标</p>
document.getElementById("demo").onclick=function(e)
{
    var e=e||event;
    alert(e.screenX);
}

浏览器内核

要搞清楚浏览器内核是什么,首先应该先搞清楚浏览器的构成。简单来说浏览器可以分为 两部分,shell+内核。其中shell的种类相对比较多,内核则比较少。Shell是指浏览器的外壳:例如菜单,工具栏等。主要是提供给用户界面操 作,参数设臵等等。它是调用内核来实现各种功能的。内核才是浏览器的核心。内核是基于标记语言显示内容的程序或模块。也有一些浏览器并不区分外壳和内核。 从Mozilla将Gecko独立出来后,才有了外壳和内核的明确划分。目前主流的浏览器有IE6/7/8、Mozilla、FireFox、Opera、Safari、Chrome、Netscape等。

什么是浏览器内核

浏览器内核又可以分成两部分:渲染引擎(layout engineer或者Rendering Engine)和JS引擎。它负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至 显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。JS引擎则是解析Javascript语言,执行javascript语言来实现网页的动态效果。最开始渲染引 擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。有一个网页标准计划小组制作了一个ACID来测试引擎的兼容性和性能。内核的种类很多,如加上没什么人使用的非商业的免费内核,可能会有10多种,但是常见的浏览器内核可以分这四种:Trident、Gecko、 Presto、Webkit。


 

渲染引擎

Trident又称MSHTML,是微软开发的渲染引擎(包含了Javascript引擎JScript),目前很多浏览器都使用这个引擎,例如IE,MaxThon,TT,The World,360,搜狗浏览器,Maxthon(最新版已经不使用)等。 Gecko是C++开发的,Open Source的渲染引擎,包括了SpiderMonkey(Rhino)。主要的使用者有Firefox,Netscape6及以上版本,MozillaSuite/SeaMonkey等 。
Webkit是苹果公司基于KHTML开发的。他包括Webcore和JavaScriptCore(SquirrelFish,V8)两个引擎。主要的使用者有Safari,Chrome。 Presto由Opera Software公司开始的,用于Opera的渲染引擎。Macromedia Dreamweaver (MX版本及以上)和Adobe Creative Suite 2也使用了Presto的内核。主要的使用者为Opera7及以上。

JS引擎

JavaScript最初由网景公司的Brendan Eich设计,是一种动态、弱类型、基于原型的语言,内臵支持类。以它为基础,制定了ECMAScript标准。他的起源并不是如《Javascript高级程序设计》书中所述,是Brendan Eich自主发明的。(参考aimingoo的考证文章)JavaScript在浏览器的实现中还必须含有DOM和BOM。Web浏览器一般使用公共API来创建主机对象来负责将DOM对象反射进JavaScript。

 

Javascript对鼠标滚轮事件的处理

 W3C并没有对鼠标滚轮事件进行规范,各浏览器厂商封装了不同的实现方法,事件属性也不一样,号称最标准的FireFox,用了一个私有实现DOMMouseScroll。不过,其他浏览器都是用onmousewheel实现,所以做兼容处理的难度也不大。

浏览器 实现方法 事件属性 向上滚动 向下滚动
FireFox DOMMouseScroll detail -3 3
非FireFox onmousewheel wheelDelta 120 -120

所谓事件属性,就是滚轮滚动时某个特定变量的变化。该变量不需要用户定义,是作为事件的属性出现的。

  • 对于FireFox,这个变量是detail:滚轮向上滚动,detail=-3;向下滚动,detail=3。
  • 对于非FireFox,这个变量是wheelDelta:滚轮向上滚动,wheelDelta=120;向下滚动,wheelDelta=-120。


另外,还有一点需要注意。

  • 在FireFox下,DOMMouseScroll必须通过addEventListener来绑定,如:
        element.addEventListener("DOMMouseScroll",fun,false)
  • 在非FireFox下,就没有限制了,除了上述方法,还可用下边的代码:
        element.onmousewheel=function(){}


笔者最后总结了一段兼容代码,给大家使用。

  • 对于实现方法的兼容:
    /**
    * 注册滚轮事件函数
    * @param ele  注册的事件对象
    * @param fun  注册事件函数
    */ 
    function mouseWheel(ele,fun)
    {
        (/firefox/i).test(navigator.userAgent)?ele.addEventListener("DOMMouseScroll",fun,false):ele.onmousewheel=fun;
    }
  • 对于事件属性的兼容:
    /**
    *  对滚轮事件属性的兼容处理,不管何种浏览器,最后统一为:鼠标轮向上滚动detail=-3,向下滚动detail=3
    */ 
    function fun(e)
    {
        var e=e||event;
        var detail=e.detail||parseInt(-e.wheelDelta/40);
        /* 添加代码 */
    }

实例:鼠标在图片上滚动,图片放大或缩小。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>效果:鼠标在图片上滚动,图片放大或缩小</title>
</head>
<body>
<img src="/uploads/allimg/121023/1-1210231013513W.jpg" />
<br /><br /><br /><br />
<img src="/uploads/allimg/121023/1-12102321502QO.png" />
<script language="JavaScript" type="text/javascript">
function fun(e)
{
    var e=e||event;
    var detail=e.detail||parseInt(-e.wheelDelta/40);
this.setAttribute("height",this.offsetHeight+4*detail);
}

function mouseWheel(ele,fun)
{
    (/firefox/i).test(navigator.userAgent)?ele.addEventListener("DOMMouseScroll",fun,false):ele.onmousewheel=fun;
}

for(var imgs=document.getElementsByTagName("img"),len=imgs.length,i=0;i<len;i++)
{
mouseWheel(imgs[i],fun)
}
</script>
</body>
</html>
 

Javascript addEventListener和attachEvent的区别

首先,Javascript有3种绑定事件监听的方法:

  1. <div onclick="alert("事件绑定成功了!")">事件绑定Demo</div>
  2. <div id="div1">事件绑定Demo</div>
    document.getElementById("div1").onclick=function(){
        alert("事件绑定成功了!");
    }
  3. <div id="div1">事件绑定Demo</div>
    function  fun(){
        alert("事件绑定成功了!");
    }
    document.getElementById("div1").addEventListener("click",fun,false);

addEventListener和attachEvent都是第三种绑定事件监听的方法,区别如下。

一、addEventListener和attachEvent的兼容性问题

  • addEventListener是符合W3C规范的事件绑定方法,FireFox、Chrome、Safari都是用它来绑定事件。
  • attachEvent是IE私有的,不符合W3C规范,而且在IE下,只能使用它来绑定事件,addEventListener是无效的。

所以,要想绑定事件,必须处理兼容性问题。

二、addEventListener和attachEvent的语法规则

  • addEventListener共有3个参数,如下所示:
    element.addEventListener(type,listener,useCapture);
    参数 参数说明
    element 要绑定事件的对象,及HTML节点。
    type 事件名称,注意去掉事件前边的“on”,比如“onclick”要写成“click”,“onmouseover”要写成“mouseover”。
    listener 要绑定的事件监听函数,注意只写函数名,不要带括号。
    userCapture 事件监听方式,只能是true和false:true,采用capture(捕获)模式;false,采用bubbling(冒泡)模式。如无特殊要求,一般是false。
    这里有必要说一下捕获模式和冒泡模式的区别。

    如图所示,有两层div元素,而且都设定有click事件,一般来说,如果我在内层蓝色的元素上click不只会触发蓝色元素的click事件,还会同时触发红色元素的click事件,而useCapture这个参数就是在控制这时候两个click事件的先后顺序。如果是false,那就会使用bubbling(冒泡)模式,他是从内而外的流程,所以会先执行蓝色元素的click事件再执行红色元素的click事件,如果是true,那就是capture(捕获)模式,和bubbling(冒泡)模式相反是由外而内,会先执行红色元素的click事件才执行蓝色元素的click事件。
    如果不同层的元素使用的useCapture不同,会先从最外层元素往目标元素寻找设定为capture(捕获)模式的事件,到达目标元素执行目标元素的事件后,再寻原路往外寻找设定为bubbling(冒泡)模式的事件。
  • attachEvent共有2个参数,如下所示:
    element.attachEvent(type,listener);
    参数 参数说明
    element 要绑定事件的对象,及HTML节点。
    type 事件名称,注意加上事件前边的“on”,比如“onclick”和“onmouseover”,这是与addEventListener的区别。
    listener 要绑定的事件监听函数,注意只写函数名,不要带括号。

三、代码兼容处理

function regEvent(ele, event_name, fun)
{
    if (window.attachEvent) 
        ele.attachEvent(event_name, fun);  //IE浏览器
    else
    {
        event_name = event_name.replace(/^on/, “”);   //如果on开头,删除on,如onclick->click
        ele.addEventListener(event_name, fun, false);  //非IE浏览器
    }
}

注意,请不要以这种方式来判断IE浏览器:
    (/msie/i).test(navigator.userAgent)
此种方法虽然简单易懂,但是有一个很大的隐患,就是浏览器升级以后支持W3C标准了,而并没有做向后兼容,这种情况下就会出现错误提示,程序崩溃,增加了维护成本。

 

本文转载自:

上一篇: HTTP状态信息
下一篇: JavaScript Cookie
wersdffg
粉丝 14
博文 86
码字总数 32304
作品 0
厦门
程序员
私信 提问
加载中

评论(1)

h
helianwen
低版本css兼容性问题可以访问:http://www.hlwen.com/fenxiang/yvlu/2015-12-09/105.html
关于浏览器模式和文本模式的困惑

什么是浏览器模式和文本模式? 经常使用IE开发者工具的同学,肯定见过浏览器模式和文本模式,对于这两个名词,综合相关文档解释如下: 浏览器模式(Browser Mode),用于切换IE针对该网页的默...

lg2045
2013/07/01
155
0
好程序员分享大势所趋 HTML5成Web开发者最关心的技术

好程序员分享大势所趋 HTML5成Web开发者最关心的技术,最近,在Stack Exchange上出现了一个比较热门的问题:Web开发者最头疼的问题是什么?结果并不是大家通常认为的兼容性问题,而是关于HTM...

好程序员IT
04/17
10
0
兼顾性能和兼容体验:HTML5时代的浏览器全面测试

  导言:自1981年IBM推出第一台PC以来,桌面电脑以及随后不断涌现的笔记本、平板以及智能手机等设备越来越普及,而近20年来互联网的出现和高速发展,则让浏览器成为这些设备上使用率最高的...

想你一起
2012/11/20
365
7
一文读懂JavaScript和ECMAScript的区别

一文读懂JavaScript和ECMAScript的区别 这篇文章代表了我目前对 JavaScript 和 ECMAScript 之间差异的理解。文章适合那些熟悉 JavaScript 但又想更加清楚地了解其与 ECMAScript、web 浏览器、...

城市之雾
2018/12/05
29
0
赶上 ECMAScript 潮流:用现代 JavaScript 编程

赶上 ECMAScript 潮流:用现代 JavaScript 编程 export const repeat = (string) => ; // main.mjsimport {repeat} from './lib.mjs';repeat('#io18'); // preload......

hijiangtao
2018/11/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

《JAVA核心知识》学习笔记 (19. 数据库)

19.1.1. 存储引擎 19.1.1.1. 概念 数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、 更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧...

Shingfi
11分钟前
2
0
三分钟手操自己的yum源

本文章原创首发公众号:编程三分钟 上次就想手操yum源了,考虑到有的朋友没接触过,直接写成了yum源的科普,活活憋了我一个星期,现在我们快快开始。 什么情况下我们需要搭建一个仓库呢? 记...

编程三分钟
15分钟前
4
0
一起来学Java8(二)——Lambda表达式

Lambda简介 什么是Lambda表达式,简单的说是一种匿名函数表达方式。因此Lambda表达式本质是个函数,只不过没有函数名称。 Lambda表达式具有以下特点: 匿名,它没有函数名称 本质是个函数,除...

猿敲月下码
17分钟前
3
0
排序算法之希尔排序

1、介绍。 希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因D...

daxiongdi
25分钟前
3
0
log4j2入门hello world

1.什么是log4j2 (1)log4j log4j是apache的一个开源项目,表示log for java.是一个日志工具,可以将日志信息输出到文件,控制台等其他地方 ,还可以定义日志的输出格式,另外还有日志级别的区分,可...

Blueeeeeee
27分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部