目錄
标准参考
问题描述
造成的影响
受影响的浏览器
问题分析
1. 只有 IE Opera 支持使用 'attachEvent' 和 'detachEvent' 方法绑定和解绑事件监听器
2. 各浏览器获取事件对象的差异
3. 各浏览器中事件对象的属性和方法的差异
解决方案
1. 使用特性判断创建无兼容性问题的事件监听器绑定和解绑函数
2. 使用特性判断获得有效的事件对象
3. 使用特性判断使用与标准对应的非标准方法及属性
首頁 web前端 js教程 事件模型在各浏览器中存在差异_javascript技巧

事件模型在各浏览器中存在差异_javascript技巧

May 16, 2016 pm 06:18 PM

标准参考

根据 W3C DOM 2 Events 描述,EventTarget 接口被所有支持 DOM 事件模型的节点(Node)实现。 该接口提供了 'addEventListener' 和 'removeEventListener' 方法,用来绑定或解绑一个 EventListeners 接口到一个 EventTarget。

DOM 2 Events 中定义了 Event 接口,用来提供事件的上下文信息,它提供了若干标准属性和方法。 实现 Event 接口的对象一般作为第一个参数传入事件处理函数,以用来提供当前事件相关的一些信息。

DOM 2 事件模型允许 DOM 实现支持事件的多模块,如果有必要,事件模型允许附加新的事件模块。 为了共同使用性的目的,DOM 会定义一个包含低级别的,依赖设备的事件模块、一个 UI 逻辑事件模块和一个文档变化事件模块的 UI 事件模块。 第三方实现(比如浏览器厂商)在定义一个新类型事件的时候,事件名称一定不能使用大小写无关的 'DOM' 字符串作开头,该前缀是为未来的 DOM 事件模块保留的。

DOM 2 已经定义了一个 UI 事件类型模块和一个鼠标事件类型的模块,它们分别对应 UIEvent 和 MouseEvent 接口。 这两个接口提供了若干标准属性和方法,以获知事件发生时的一些信息。

关于 EventTarget 接口的详细信息,请参考 DOM 2 Events 1.3. Event listener registration

关于 Event 接口的详细信息,请参考 DOM 2 Events 1.4. Event interface

关于事件模块的详细信息,请参考 DOM 2 Events 1.6. Event module definitions

问题描述

各浏览器对元素绑定、解绑事件监听器的方法,事件对象的获取,以及 Event 对象的实现上存在差异。

造成的影响

如果使用某浏览器特有的事件相关的属性及方法编写代码,则可能造成兼容性问题,导致代码报错,功能失效。

受影响的浏览器

所有浏览器  

问题分析

1. 只有 IE Opera 支持使用 'attachEvent' 和 'detachEvent' 方法绑定和解绑事件监听器

根据 DOM 2 Events 中描述,节点使用 'addEventListener' 和 'removeEventListener' 方法绑定和解绑事件监听器,但 IE6 IE7 IE8 不支持这两个方法, 而使用 'attachEvent' 和 'detachEvent' 方法作为替代方案,Opera 两类方法都支持。Chrome Safari Firefox 只支持标准方法。

分析以下代码:

<button id="add" type="button">add event listener test</button>
<button id="remove" type="button">remove event listener test</button>
<div id="info"></div>
<script type="text/javascript">
	var add = document.getElementById("add"),
		remove = document.getElementById("remove"),
		showMsgA = function(){showMsg("attachEvent")},
		showMsgB = function(){showMsg("addEventListener")};

	if(add.attachEvent){
		add.attachEvent("onclick",showMsgA);
		remove.attachEvent("onclick",removeE);
	}

	if(add.addEventListener){
		add.addEventListener("click",showMsgB,false);
		remove.addEventListener("click",removeE,false);
	}

	function removeE(){
		if(add.detachEvent){
			add.detachEvent("onclick",showMsgA);
			showMsg("detachEvent");
		}

		if(add.removeEventListener){
			add.removeEventListener("click",showMsgB,false);
			showMsg("removeEventListener");
		}
	}

	function showMsg(method){
		document.getElementById("info").innerHTML += ("support " + method + "<br />");
	}
</script>
登入後複製

依次点击 'add event listener test' >> 'remove event listener test' >> 'add event listener test',测试各浏览器对这些方法的支持,结果如下:

IE6 IE7 IE8
Opera
Chrome Safari Firefox

关于 'addEventListener' 和 'attachEvent' 有几点需要注意:

  • IE 不支持在捕获阶段触发事件监听器,'attachEvent' 方法没有提供参数说明是否响应在捕获阶段触发的事件;
  • 'addEventListener' 和 'attachEvent' 都可以注册多个事件监听器;
  • 在 Firefox Chrome Safari Opera 中给同一事件注册同一个事件监听器多次,重复注册的会被丢弃;而在 IE 中重复注册的事件监听器会被重复执行多次;
  • 当给同一元素注册了多个事件监听器的时候,IE6 IE7 的事件监听器执行顺序是随机的,IE8 是倒序的,Firefox Chrome Safari Opera 是顺序的;
  • 当元素注册的事件监听器中有非法的事件监听器时(非函数),在 IE Firefox 中会抛出异常,而在 Chrome Safari Opera 中则会忽略非法的事件监听器,继续执行其他的事件监听器。

2. 各浏览器获取事件对象的差异

DOM 2 Events 中规定使用事件监听器的第一个参数作为事件对象,而 IE Opera Chrome Safari 还支持通过 window.event 获取事件对象。

分析以下代码:

<button type="button" id="attach">attachEvent</button>
<button type="button" id="addE">addEventListener</button>
<button type="button" id="byclick">onClick</button>
<br>
INFO :
<div id="info"></div>

<script type="text/javascript">
	function $(id){return document.getElementById(id);}
	var attach = $("attach"),
		addE = $("addE"),
		byClick = $("byclick");

	attach.attachEvent && attach.attachEvent("onclick", handler);
	addE.addEventListener && addE.addEventListener("click", handler, false);
	byClick.onclick = handler;

	function handler(){
		var src = window === this ? window.event.srcElement : this, type = src.innerHTML;
		window.event && showMsg(window.event.type, type + " + window.event");
		arguments[0] && showMsg(arguments[0].type, type + " + arguments[0]");
	}
	function showMsg(type, msg){
		$("info").innerHTML += (msg + "(type : " + type + ")<br />");
	}
</script>
登入後複製

以上代码组合不同的事件监听器绑定方式和事件对象获取方法,测试各浏览器的支持程度。

依次点击 'attachEvent' >> 'addEventListener' >> 'onClick',结果如下:

IE6 IE7 IE8 事件模型在各浏览器中存在差异_javascript技巧
Chrome Safari 事件模型在各浏览器中存在差异_javascript技巧
Opera 事件模型在各浏览器中存在差异_javascript技巧
Firefox 事件模型在各浏览器中存在差异_javascript技巧

汇总测试结果如下表:1

事件对象获取方式 IE6 IE7 IE8 Chrome Safari Opera Firefox
window.event Y Y Y N
arguments[0] Y2 Y Y Y

注1: Y 表示支持该事件对象获取方式,N 表示不支持。

注2: 部分支持。

从上表出可以看出:

  • 只有在使用 attachEvent 方法注册事件监听器的时候,IE 才支持使用事件监听器传入的第一个参数作为事件对象的方式;
  • Chrome Safari Opera 两种获取事件对象的方式都支持;
  • Firefox 只支持获取事件对象的标准方式。

3. 各浏览器中事件对象的属性和方法的差异

IE 对事件对象的标准属性和方法支持有限,针对大部分属性和方法,IE 都提供了一套替代非标准的替代方案; 而 Firefox Chrome Safari Opera 除了全面支持事件对象的标准属性和方法外,还在不同程度上支持了 IE 提供的非标准替代方案。

以下代码检测了 Event、UIEvent、MouseEvent 接口以及事件对象的非标准属性在各浏览器下的支持程度:

<button type="button" id="iEvent">Interface Event</button>
<button type="button" id="iUIMouse">Interface UIEvent & MouseEvent</button>
<input type="text" id="nosK">
<p id="wrap" style="border:3px solid;padding:5px;width:500px;"><a id="nosCM" href="#"><img src="/static/imghw/default1.png" data-src="google.gif" class="lazy" alt="IE"></a></p>
<br>
登入後複製
Interface Event
Interface UIEvent
&
MouseEvent
Non-standard
&
click
Non-standard
&
mouseover mouseout
Non-standard
&
keyCode

执行以上测试代码,分别点击 'Interface Event' 按钮、'Interface UIEvent & MouseEvent' 按钮和图片,鼠标移到图片上再移开,在文本框中输入 'a',得到结果整理如下表:3

Interface & Non-standard Property & method IE6 IE7 IE8 Chrome Safari Opera Firefox
Interface Event type Y Y Y
target N Y Y
currentTarget N Y Y
eventPhase N Y Y
bubbles N Y Y
cancelable N Y Y
timeStamp N Y Y
initEvent N Y Y
preventDefault N Y Y
stopPropagation N Y Y
Interface UIEvent view N Y Y
detail N Y Y
initUIEvent N Y Y
Interface MouseEvent screenX Y Y Y
screenY Y Y Y
clientX Y Y Y
clientY Y Y Y
ctrlKey Y Y Y
shiftKey Y Y Y
altKey Y Y Y
metaKey N Y Y
button Y Y Y
relatedTarget N Y Y
initMouseEvent N Y Y
Non-standard cancelBubble Y Y Y
offsetX Y Y N
offsetY Y Y N
returnValue Y Y N
srcElement Y Y N
x Y Y N
y Y Y N
fromElement Y Y N
toElement Y Y N
keyCode Y Y Y

注3: Y 代表事件对象支持该属性或方法,N 代表不支持。

从上表中可以看出:

  • IE 支持事件对象的所有非标准属性,不支持除 'type' 外 Event 接口的所有方法属性及方法,不支持 UIEvent 接口的所有属性和方法,不支持 MouseEvent 接口的 'metaKey'、'relatedTarget' 属性和 'initMouseEvent' 方法;
  • Chrome Safari Opera 支持事件对象的所有标准及非标准的属性和方法;
  • Firefox 支持事件对象的所有标准属性和方法,但仅支持非标准属性中的 'cancelBubble' 和 'keyCode'。

需要注意的是:

  • Firefox 不支持事件对象的 'returnValue' 属性,测试样例中虽然显示 'returnValue' 值为 false,但这仅仅是因为给事件对象添加了 'returnValue' 属性,并没有起到取消事件默认动作的作用,这从地址栏可以看出,多了 '#' 号,这是 A 标签的 'href' 属性造成的。
  • 各浏览器对 Event 接口的 'timeStamp' 属性返回值都不同。

关于 IE 实现的事件对象非标准的属性及方法的详细信息,请参考 MSDN event Object

关于 Firefox 对事件对象实现的详细信息,请参考 MDC event

解决方案

1. 使用特性判断创建无兼容性问题的事件监听器绑定和解绑函数

如:

function addEvent(elem, type, handler, useCapture){
	elem.addEventListener ? elem.addEventListener(type, handler, useCapture) :
		elem.attachEvent("on" + type, handler);
}

function removeEvent(elem, type, handler, useCapture){
	elem.removeEventListener ? elem.removeEventListener(type, handler, useCapture) :
		elem.detachEvent("on" + type, handler);
}
登入後複製

2. 使用特性判断获得有效的事件对象

在事件监听器中判断传入的第一个参数或 window.event 是否有效,如:

function handler(e){
	e = e || window.event;
}
登入後複製

3. 使用特性判断使用与标准对应的非标准方法及属性

尽管 IE 对事件对象的标准属性和方法支持有限,但它自己实现的事件模型也基本能够替代或实现标准属性或方法的功能。

下表总结了部分与标准事件对象对应的,或可以实现标准属性或方法功能的非标准属性:

Standard Non-standard
target srcElement
preventDefault() returnValue
stopPropagation() cancelBubble
relatedTarget fromElement toElement

另,标准的 'clientX' 属性和非标准的 'x' 属性作用是相同的,同样 'clientY' 和 'y' 也是。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何創建和發布自己的JavaScript庫? 如何創建和發布自己的JavaScript庫? Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

如何在瀏覽器中優化JavaScript代碼以進行性能? 如何在瀏覽器中優化JavaScript代碼以進行性能? Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

如何使用瀏覽器開發人員工具有效調試JavaScript代碼? 如何使用瀏覽器開發人員工具有效調試JavaScript代碼? Mar 18, 2025 pm 03:16 PM

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

如何使用源地圖調試縮小JavaScript代碼? 如何使用源地圖調試縮小JavaScript代碼? Mar 18, 2025 pm 03:17 PM

本文說明瞭如何使用源地圖通過將其映射回原始代碼來調試JAVASCRIPT。它討論了啟用源地圖,設置斷點以及使用Chrome DevTools和WebPack之類的工具。

如何有效地使用Java的收藏框架? 如何有效地使用Java的收藏框架? Mar 13, 2025 pm 12:28 PM

本文探討了Java收藏框架的有效使用。 它強調根據數據結構,性能需求和線程安全選擇適當的收集(列表,設置,地圖,隊列)。 通過高效優化收集用法

初學者的打字稿,第2部分:基本數據類型 初學者的打字稿,第2部分:基本數據類型 Mar 19, 2025 am 09:10 AM

掌握了入門級TypeScript教程後,您應該能夠在支持TypeScript的IDE中編寫自己的代碼,並將其編譯成JavaScript。本教程將深入探討TypeScript中各種數據類型。 JavaScript擁有七種數據類型:Null、Undefined、Boolean、Number、String、Symbol(ES6引入)和Object。 TypeScript在此基礎上定義了更多類型,本教程將詳細介紹所有這些類型。 Null數據類型 與JavaScript一樣,TypeScript中的null

開始使用Chart.js:PIE,DONUT和BUBBLE圖表 開始使用Chart.js:PIE,DONUT和BUBBLE圖表 Mar 15, 2025 am 09:19 AM

本教程將介紹如何使用 Chart.js 創建餅圖、環形圖和氣泡圖。此前,我們已學習了 Chart.js 的四種圖表類型:折線圖和條形圖(教程二),以及雷達圖和極地區域圖(教程三)。 創建餅圖和環形圖 餅圖和環形圖非常適合展示某個整體被劃分為不同部分的比例。例如,可以使用餅圖展示野生動物園中雄獅、雌獅和幼獅的百分比,或不同候選人在選舉中獲得的投票百分比。 餅圖僅適用於比較單個參數或數據集。需要注意的是,餅圖無法繪製值為零的實體,因為餅圖中扇形的角度取決於數據點的數值大小。這意味著任何占比為零的實體

See all articles