js 实现一些跨浏览器的事件方法详解及实例

JavaScript012

js 实现一些跨浏览器的事件方法详解及实例,第1张

js实现一些跨浏览器的事件方法

用JavaScript实现事件的绑定,移除,以及一些常用的事件属性的获取,时常要考虑到在不同浏览器下的兼容性,下面给出了一个跨浏览器的事件对象:

var

EventUtil

=

{

on:

function(element,

type,

handler)

{/*

添加事件

*/

if

(element.addEventListener)

{

element.addEventListener(type,

handler,

false)

}

else

if

(element.attachEvent)

{//IE

注意:此时事件处理程序会在全局作用域中运行,因此用attachEvent绑定的事件,此时在事件处理函数里的this

等于window,使用时要注意

element.attachEvent("on"

+

type,

handler)

}

else

{

element["on"

+

type]

=

handler

}

},

off:

function(element,

type,

handler)

{/*

移除事件

*/

if

(element.removeEventListener)

{

element.removeEventListener(type,

handler,

false)

}

else

if

(element.detachEvent)

{

element.detachEvent("on"

+

type,

handler)

}

else

{

element["on"

+

type]

=

null

}

},

getEvent:

function(event)

{/*

返回对event对象的引用

*/

return

event

?

event

:

window.event

},

getTarget:

function(event)

{/*

返回事件的目标

*/

return

event.target

||

event.srcElement

},

preventDefault:

function(event)

{

/*

取消事件的默认行为

*/

if

(event.preventDefault)

{

event.preventDefault()

}

else

{

event.returnValue

=

false

}

},

stopPropagation:

function(event)

{/*

阻止事件冒泡

*/

if

(event.stopPropagation)

{

event.stopPropagation()

}

else

{

event.cancelBubble

=

true

}

},

/*

mouseover

和mouserout

这两个事件都会涉及把鼠标指针从一个元素的边界之内移动到另一个元素的边界之内。*/

getRelatedTarget:

function(event)

{

if

(event.relatedTarget)

{

return

event.relatedTarget

}

else

if

(event.toElement)

{//IE8

mouserout事件

return

event.toElement

}

else

if

(event.fromElement)

{//IE8

mouseover事件

return

event.fromElement

}

else

{

return

null//其他事件

}

}

}

调用如下:

EventUtil.on(document,

"click",

function(event){//为document元素绑定click事件

event

=

EventUtil.getEvent(event)//获取event事件对象

alert("Screen

coordinates:

"

+

event.screenX

+

","

+

event.screenY)

})

文章参考自《JavaScript高级程序设计第三版》

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

IE

左键是

window.event.button

=

1

右键是

window.event.button

=

2

中键是

window.event.button

=

4

没有按键动作window.event.button

=

0

Firefox

左键是

event.button

=

0

右键是

event.button

=

2

中键是

event.button

=

1

没有按键动作

event.button

=

0

Opera

7.23/7.54

鼠标左键是

window.event.button

=

1

没有按键动作

window.event.button

=

1

右键和中键无法获取

Opera

7.60/8.0

鼠标左键是

window.event.button

=

0

没有按键动作

window.event.button

=

0

右键和中键无法获取

另外:屏蔽右键的是window.event.button

=

3

************************************************************

Window.event对象代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等。

Window.event对象只在事件发生的过程中才有效。

Window.event的某些属性只对特定的事件有意义。比如,fromElement

toElement

属性只对

onmouseover

onmouseout

事件有意义。

如果事件触发后,鼠标移出窗口外,则返回的值为

-1

,这是个只读属性。这意味着,你只能通过它来得到鼠标的当前位置,却不能用它来更改鼠标的位置。

Event对象的属性有:

altKey,

button,

cancelBubble,

clientX,

clientY,

ctrlKey,

fromElement,

keyCode,

offsetX,

offsetY,

propertyName,

returnValue,

screenX,

screenY,

shiftKey,

srcElement,

srcFilter,

toElement,

type,

x,

y

下面简单的描述一下它的这些属性:

1.altKey

描述:

检查alt键的状态。

语法:

event.altKey

可能的值:

当alt键按下时,值为

TRUE

,否则为

FALSE

。只读。

2.button

描述:

检查按下的鼠标键。

语法:

event.button

可能的值:

0

没按键

;1

按左键

;2

按右键

;3

按左右键

;4

按中间键

;5

按左键和中间键

;6

按右键和中间键

;7

按所有的键

这个属性仅用于onmousedown,

onmouseup,

onmousemove

事件。对其他事件,不管鼠标状态如何,都返回

0(比如onclick)。

3.cancelBubble

描述:

检测是否接受上层元素的事件的控制。

语法:

event.cancelBubble[

=

cancelBubble]

可能的值:

这是一个可读写的布尔值

TRUE

不被上层原素的事件控制。

FALSE

允许被上层元素的事件控制。这是默认值。

4.clientX

描述:

返回鼠标在窗口客户区域中的X坐标。

语法:

event.clientX

注释:

这是个只读属性。这意味着,你只能通过它来得到鼠标的当前位置,却不能用它来更改鼠标的位置。

5.clientY

描述:

返回鼠标在窗口客户区域中的Y坐标。

语法:

event.clientY

注释:

这是个只读属性。这意味着,你只能通过它来得到鼠标的当前位置,却不能用它来更改鼠标的位置。

6.ctrlKey

描述:

检查ctrl键的状态。

语法:

event.ctrlKey

可能的值:

当ctrl键按下时,值为

TRUE

,否则为

FALSE

。只读。

7.fromElement

描述:

检测

onmouseover

onmouseout

事件发生时,鼠标所离开的元素。

参考18.toElement

语法:

event.fromElement

注释:

这是个只读属性。

8.keyCode

描述:检测键盘事件相对应的内码。

这个属性用于

onkeydown,

onkeyup,

onkeypress

事件。

语法:

event.keyCode[

=

keyCode]

可能的值:

这是个可读写的值,可以是任何一个Unicode键盘内码。如果没有引发键盘事件,则该值为

0

9.offsetX

描述:

检查相对于触发事件的对象,鼠标位置的水平坐标

语法:

event.offsetX

10.offsetY

描述:

检查相对于触发事件的对象,鼠标位置的垂直坐标

语法:

event.offsetY

11.propertyName

描述:

设置或返回元素的变化了的属性的名称。

语法:

event.propertyName

[

=

sProperty

]

可能的值:

sProperty

是一个字符串,指定或返回触发事件的元素在事件中变化了的属性的名称。

注释:这个属性是可读写的。无默认值。你可以通过使用

onpropertychange

事件,得到

propertyName

的值。

12.returnValue

描述:

设置或检查从事件中返回的值

语法:

event.returnValue[

=

Boolean]

可能的值:

true

事件中的值被返回

false

源对象上事件的默认操作被取消

13.screenX

描述:

检测鼠标相对于用户屏幕的水平位置

语法:

event.screenX

注释:

这是个只读属性。这意味着,你只能通过它来得到鼠标的当前位置,却不能用它来更改鼠标的位置。

14.screenY

描述:

检测鼠标相对于用户屏幕的垂直位置

语法:

event.screenY

注释:

这是个只读属性。这意味着,你只能通过它来得到鼠标的当前位置,却不能用它来更改鼠标的位置。

15.shiftKey

描述:

检查shift键的状态。

语法:

event.shiftKey

可能的值:

当shift键按下时,值为

TRUE

,否则为

FALSE

。只读。

16.srcElement

描述:

返回触发事件的元素。只读。例子见本文开头。

语法:

event.srcElement

17.srcFilter

描述:

返回触发

onfilterchange

事件的滤镜。只读。

语法:

event.srcFilter

18.toElement

描述:

检测

onmouseover

onmouseout

事件发生时,鼠标所进入的元素。

参考7.fromElement

语法:

event.toElement

注释:

这是个只读属性。

19.type

描述:

返回事件名。

语法:

event.type

注释:

返回没有“on”作为前缀的事件名,比如,onclick事件返回的type是click

只读。

20.

x

描述:

返回鼠标相对于css属性中有position属性的上级元素的x轴坐标。如果没有css属性中有position属性的上级元素,默认以BODY元素作为参考对象。

语法:

event.x

注释:

如果事件触发后,鼠标移出窗口外,则返回的值为

-1

这是个只读属性。这意味着,你只能通过它来得到鼠标的当前位置,却不能用它来更改鼠标的位置。

21.

y

描述:

返回鼠标相对于css属性中有position属性的上级元素的y轴坐标。如果没有css属性中有position属性的上级元素,默认以BODY元素作为参考对象。

语法:

event.y

一.关于获取事件对象

FF有点倔强,只支持arguments[0],不支持window.event。这次真的不怪IE,虽然把event作为window的属性不合规范,但大家都已经默许这个小问题存在了,只有FF这么多年了还是特立独行。所以,跨浏览器的事件对象获取有以下两种方式:

带参的:

?

1

2

3

4

getEvent : function(event){

return event ? event : window.event

//return event || window.event//或者更简单的方式

}

无参的:

?

1

2

3

4

function getEvent() {

return arguments[0] ? arguments[0] : window.event

//return arguments[0] || window.event//或者更简单的方式

}

需要特别说明一种方式:HTML的DOM0级方式 + 带参的事件处理器,如下:

?

1

2

3

4

function handler(event){

//do something

}

<!-- HTML的DOM0级方式 --><br><button id="btn" onclick="handler(event)">按钮</button><br>

上面这种方式是全浏览器兼容的,但依赖HTML的DOM0级方式的缺点很明显,所以没能成为像前两种那样的主流方法,而JS的DOM0级方式 + 带参的事件处理器,如下:

?

1

2

3

4

5

function handler(event){

//do something

}

btn.onclick = handler//JS的DOM0级方式

//btn.onclick = function(event){/*do something*/}//或者匿名函数,效果同上

这种方式不是全浏览器兼容的,[IE8-]不支持,IE9+未知,FF,Chrome支持。一直以为HTML的DOM0级事件处理和JS的DOM0级事件处理是等价的,现在做了很多实验才发现二者是有区别的

二.关于获取事件源

event.srcElement是[IE8-]唯一的方式,IE9+未知,其它浏览器都支持标准的event.target方式

三.关于阻止事件默认行为

event.preventDefault()是标准方法,但[IE8-]不支持,IE自己的方式是event.returnValue = false

四.关于停止事件传播

event.stopPropagation()是标准方法,IE又有意见了,他要这么玩:event.cancelBubble = true这里需要特别注意了,因为cancel是属性而不是方法,与标准相差甚远,容易记错

五.关于事件处理器的添加和移除

DOM0级方式

ele.onclick = handlerele.onclick=null最古老的一种方式

优点:全浏览器兼容

缺点:同一事件只能绑定/解绑一个事件处理器

DOM2级方式

?

1

ele.add/removeEventListener(eventType, handler, catch)

和IE方式:ele.attach/detachEvent(‘on'+eventType, handler)

优点:支持绑定/解绑多个事件处理器

缺点:需要做兼容性判断。需要注意的是:标准方式中最后一个参数表示是否在事件捕获阶段绑定/解绑,IE不支持事件捕获,所以也就没有第三个参数了

注意:IE方式不仅方法名与标准不同,参数中事件类型还要加上on,否则绑定无效但不报错

六.跨浏览器的事件处理

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

//跨浏览器的事件处理器添加方式

var EventUtil = {

addHandler : function(elem, type, handler){

if(elem.addEventListener){

elem.addEventListener(type, handler, false)

}

else if(elem.attachEvent){

elem.attachEvent("on" + type, handler)//添加多个同一类型的handler时,IE方式的规则是最后添加的最先触发

}

else{

if(typeof elem["on" + type] === 'function'){

var oldHandler = elem["on" + type]

elem["on" + type] = function(){

oldHandler()

handler()

}

}

else{

elem["on" + type] = handler//支持添加多个事件处理器

}

}

},

getEvent : function(event){

return event ? event : window.event

},

getTarget : function(event){

return event.target || event.srcElement

},

preventDefault : function(event){

if(event.preventDefault){

event.preventDefault()

}

else{

event.returnValue = false

}

},

removeHandler : function(elem, type, handler){

if(elem.removeEventListener){

elem.removeEventListener(type, handler, false)

}

else if(elem.detachEvent){

elem.detachEvent("on" + type, handler)

}

else{

elem["on" + type] = null//不支持移除单一事件处理器,只能全部移除

}

},

stopPropagation : function(event){

if(event.stopPropagation){

event.stopPropagation()

}

else{

event.cancelBubble = true

}

},

getRelatedTarget : function(event){

if(event.relatedTarget){

return event.relatedTarget

}

else if(event.toElement &&event.type == "mouseout"){

return event.toElement

}

else if(event.fromElement &&event.type == "mouseover"){

return event.fromElement

}

else{

return null

}

},

/*IE8点击左键和中键都是0;FF无法识别中键;Chrome正常*/

getButton : function(event){//返回0,1,2 - 左,中,右

if(document.implementation.hasFeature("MouseEvents", "2.0")){

return event.button

}

else{

switch(event.button){

case 0:case 1:case 3:case 5:case 7:

return 0

break

case 2:case 6:

return 2

break

case 4:

return 1

break

default:

break

}

}

},

/*只能检测keypress事件,返回值等于将要显示的字符编码*/

/*IE和Chrome只有能显示的字符键才触发,FF其它键也能触发,返回值为0*/

getCharCode : function(event){

if(typeof event.charCode == "number"){

return event.charCode

}

else{

return event.keyCode

}

}

}

综合示例

如果项目中没有使用诸如 jQuery 之类的库,如何方便地为元素绑定事件,并兼容各种浏览器呢?下面这个简单的 Utility 应该可以考虑。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

var eventUtility = {

addEvent : function(el, type, fn) {

if(typeof addEventListener !== "undefined") {

el.addEventListener(type, fn, false)

} else if(typeof attachEvent !== "undefined") {

el.attachEvent("on" + type, fn)

} else {

el["on" + type] = fn

}

},

removeEvent : function(el, type, fn) {

if(typeof removeEventListener !== "undefined") {

el.removeEventListener(type, fn, false)

} else if(typeof detachEvent !== "undefined") {

el.detachEvent("on" + type, fn)

} else {

el["on" + type] = null

}

},

getTarget : function(event) {

if(typeof event.target !== "undefined") {

return event.target

} else {

return event.srcElement

}

},

preventDefault : function(event) {

if(typeof event.preventDefault !== "undefined") {

event.preventDefault()

} else {

event.returnValue = false

}

}

}

使用方法示例:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

var eventHandler = function(evt) {

var target = eventUtility.getTarget(evt),

tagName = target.tagName

if(evt.type === "click") {

if(tagName === "A" || tagName === "BUTTON") {

alert("You clicked on an A element, and the innerHTML is " + target.innerHTML + "!")

eventUtility.preventDefault(evt)

}

} else if(evt.type === "mouseover" &&tagName === "A") {

alert("mouseovered " + target.innerHTML)

}

}

eventUtility.addEvent(document, "click", eventHandler)

eventUtility.addEvent(document, "mouseover", eventHandler)

eventUtility.removeEvent(document, "mouseover", eventHandler)