JavaScript中的事件

JavaScript与HTML的交互是通过事件实现的,事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,是用户或浏览器自身执行的某种动作,例如click,mouseover等都是事件名。

(一)事件流

事件流描述的是从页面中接收事件的顺序。

1)事件冒泡

IE中的事件流叫做事件冒泡,即事件开始是由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。如下例1.1所示:

<html>
<head>
	<title> Event Bubbling Example </title>
</head>
<body>
	<div id="myDiv">Click Me</div>
</body>
</html>

若单击<div>元素,那么click事件会按照如下顺序传播:

a)<div>

b)<body>

c)<html>

d)<document>

click事件会在<div>元素上发生,然后沿着DOM树向上传播,在每一级节点上都发生,直到传播到document对象。如下图所示:

所有现代浏览器都支持事件冒泡,但有区别。IE5.5及更早的版本的事件冒泡跳过<html>元素,直接从<body>到<document >,Firefox、Chrome和Safari则将事件一直冒泡到window对象。下面为一个事件冒泡实例,使用JQuery实现:

<!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=utf-8" />
<title>Event Bubbling Example</title>
<style type="text/css">
*{margin:0;padding:0;}	
body { font-size: 13px; line-height: 130%; padding: 60px; }
#content { width: 220px; border: 1px solid #0050D0;background: #96E555 }
span { width: 200px; margin: 10px; background: #666666; cursor: pointer;color:white;display:block;}
p {width:200px;background:#888;color:white;height:16px;}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
	// 为span元素绑定click事件
	$('span').bind("click",function(){
		var txt = $('#msg').html() + "<p>内层span元素被点击.<p/>";
		$('#msg').html(txt);
	});
	// 为div元素绑定click事件
	$('#content').bind("click",function(){
	    var txt = $('#msg').html() + "<p>外层div元素被点击.<p/>";
		$('#msg').html(txt);
	});
	// 为body元素绑定click事件
	$("body").bind("click",function(){
		var txt = $('#msg').html() + "<p>body元素被点击.<p/>";
		$('#msg').html(txt);
	});
})
</script>
</head>
<body>
<div id="content">
	外层div元素
	<span>内层span元素</span>
	外层div元素
</div>

<div id="msg"></div>
</body>
</html>
单击最内层<span>元素时,显示结果如下:

2)事件捕获

事件捕获的思想是不太具体的节点应该更早接收事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于事件到达预定目标之前捕获它。在例1.1中,那么单击<div>元素会以下列顺序触发click事件:

a)document

b)<html>

c)<body>

d)<div>

事件捕获中,document对象首先接收到click事件,然后沿着DOM树依次向下,一直传播到事件的实际目标,即<div>元素。如下图所示:

3)DOM事件流

“DOM2级事件”规定了事件流的三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。例1.1中单击<div>元素会按照下图触发事件:


在DOM事件流中,实际的目标(<div>元素)在捕获阶段不会接收事件。在捕获阶段,事件从document到<html>再到<body>后就停止了;下一个阶段是“处于目标”阶段,于是事件在<div>上发生,并在事件处理中被看成冒泡的一部分;然后是冒泡阶段,事件又传播回文档。

除了IE不支持DOM事件流,其余四大主流浏览器都支持。

(二)事件处理程序

响应某个事件的函数就叫做事件处理程序,或称为事件侦听器。事件处理程序都是以"on"开头的。例如onclick、onload事件。

下面介绍为事件指定处理程序的几种方法:

1)HTML事件处理程序

某个元素支持每种事件,都可以使用一个与相应事件处理程序同名的HTML特性表示。该特性的值是能够执行的JavaScript代码。如下例所示:

<input type="button" value="Click Me" οnclick="alert('Clicked')"/>
也可以使用下述方法,先定义事件处理程序执行的具体动作:

<script type="text/javascript">	
	function showMessage(){
		alert("hello world!");
	}
</script>
<input type="button" value="Click Me" οnclick=" showMessage()" />
事件处理程序也可以被包含在独立的外部文件中,事件处理程序中的代码在执行时,有权利访问全局作用域中的任何代码。

HTML事件处理程序缺点:

a)时差问题。用户可能在HTML元素一出现就触发相应事件,而此时事件处理程序有可能还不具备执行条件。

上例中若showMessage()函数在按钮的下方,页面的最底部定义时,若用户在解析showMessage()函数之前就单击按钮,就会引发错误。需将事件错误处理程序放在一个try-catch块中。

<input type="button" value="Click Me" οnclick="try{showMessage();} catch(ex){}"/>
b)HTML与JS代码紧密耦合。

2)DOM0级事件处理程序

通过js指定事件处理程序的传统方法,就是将一个函数赋值给一个事件处理程序的属性。该方法比较简单,而且具有跨浏览器的优势。

在使用js指定事件处理程序时,需要指定一个操作对象的引用。每个元素(包括window和document)都有自己的事件处理程序属性,属性通常全部小写,例如onclick。

var btn=document.getElementById("myBtn");
btn.οnclick=function(){
    alert("Clicked");
};
该方法指定的事件处理程序被认为是元素的方法,在元素的作用域中运行的。

var btn=document.getElementById("myBtn");
btn.οnclick=function(){
    alert(this.id);  //"myBtn"
};
可以在任何事件处理程序中通过this访问元素的任何属性和方法。以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。

也可以删除DOM0级方法中指定的事件处理程序。

btn.οnclick=null;  //删除事件处理程序

HTML事件处理程序中。onclick属性就是一个包含着同名HTML特性中指定的代码的函数,也可设置相应的属性为null,删除这种指定的事件处理程序。

3)DOM2级事件处理程序

定义两种方法用于指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。

这两种方法介绍三个参数:要处理的事件名,作为事件处理程序的函数和一个布尔值。

布尔值为true表示在捕获阶段调用事件处理程序,如果为false表示在冒泡阶段调用事件处理程序。如下例所示:

a)addEventListener()

var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
	alert("this.id");
},false);
该方法添加的事件处理程序也是在元素的作用域中运行的。

使用此方法的好处是可以添加多个事件处理程序,如下例所示:

var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
	alert("this.id");
},false);
btn.addEventListener("click",function(){
	alert("Hello World!");
},false);
这两种事件处理程序会按照添加它们的顺序触发。
b)removeEventListener()

通过addEventListener()添加的事件处理程序只能通过removeEventListener()来删除,而且需要传入的参数与添加事件处理程序的参数相同

var btn=document.getElementById("myBtn");
btn.addEventListener("click",function(){
	alert("this.id");
},false);
//省略其他的代码
btn.removeEventListener("click",function(){  //没有用!传入的是完全不同的函数
	alert("this.id");
},false);

可使用下例方法:

var btn=document.getElementById("myBtn");
var handler=function(){
	alert("this.id");
};
btn.addEventListener("click",handler,false);

//省略其他的代码
btn.removeEventListener("click",handler,false);
大多数都是将事件处理程序添加到事件流中的冒泡阶段,可以更好的兼容更多的浏览器。

4)IE事件处理程序

IE中使用与DOM类似的两种方法:attachEvent()和detachEvent()。只接受相同的两个参数:事件处理程序名称和事件处理程序函数。IE只支持冒泡。

a)attachEvent()

var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){  //参数为onclick,与DOM中addEventListener中的参数不同
        alert("Clicked");
});
此方法中的事件处理程序会在全局作用域中运行,因此this等于window,如下例所示:

var btn=document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
	alert(this==window); //true
});
attachEvent()也可以为一个元素添加多个事件处理程序。但添加的事件处理程序不是以添加的顺序执行,而是以相反的顺序被触发。

b)detachEvent()

两种方法的参数必须是相同的,意味着添加的匿名函数将不能被移除。可使用下述方法,将保存在变量handler中的函数作为事件处理程序:

var btn=document.getElementById("myBtn");
var handler=function(){
	alert("Clicked");
};
btn.attachEvent("onclick",handler);
btn.detachEvent("onclick",handler);

5)跨浏览器的事件处理程序

创建方法addHandler()方法和removeHandler()方法,方法属于一个EventUtil对象,用于添加和移除事件处理成程序。如下所示:

//跨浏览器的事件处理程序
var EventUtil={
	addHandler:function(element,type,handler){
		if(element.addEventListener){  //检测DOM2级方法
			element.addEventListener(type,handler,false);
		} else if(element.attachEvent){  //检测IE方法
			element.attachEvent("on"+type,handler);
		} else{
			element["on"+type]=handler;   //使用DOM0方法
		}
	},
	removeHandler:function(element,type,handler){
		if(element.removeEventListener){  //检测DOM2级方法
			element.removeEventListener(type,handler,false);
		} else if(element.detachEvent){  //检测IE方法
			element.detachEvent("on"+type,handler);
		} else{
			element["on"+type]=null;   //使用DOM0方法
		}
	}
};
可以像下面这样使用EventUtil对象:

var btn=document.getElementById("myBtn");
var handler=function(){
	alert("Clicked");
};
EventUtil.addHandler(btn,"click",handler);
//省略其他代码
EventUtil.removeHandler(btn,"click",handler);

该两种方法仅用来添加和移除事件处理程序,并没有考虑所有的浏览器问题,例如IE中作用域问题。

未完待续(*^__^*)

参考:《JavaScript高级程序设计(第二版)》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值