事件机制

本文介绍了事件流的概念,包括冒泡和捕获两种模式,并详细探讨了四种事件绑定方式及其特点。此外,还提供了模拟多绑及jQuery风格事件绑定的实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

一  两种事件类型

 

    其实是事件流的顺序,看下面的html代码当单击链接会发生什么呢?

<html>
	<head></head>
	<body onclick="javascript:alert('body')">
		<div onclick="javascript:alert('div')">
				<a href="#" onclick="javascript:alert('a')">链接</a>
		</div>
	</body>
</html>

      当单击链接时会弹出提示a->div->body,说明单击事件会层层上抛给dom元素。这种有最准确的dom元素开始一直上抛事件源的事件流也叫冒泡。

      IE仅仅支持事件的冒泡,在firefox下面还有一种叫事件的捕获,他的过程跟冒泡刚刚相反。

<html>
	<head>
			<script>
				
				function alterMsg(msg){
						return function(){
							alert(msg);
						};
				}				
				window.onload=function(){
					 var oBody = document.body;
					 var oDiv =  document.getElementsByTagName("div")[0];
					 var oHref =  document.getElementsByTagName("a")[0];
					 
					 oDiv.addEventListener("click",  alterMsg("div"), true);
					 oBody.addEventListener("click", alterMsg("body"), true);
					 oHref.addEventListener("click", alterMsg("a"), true);	
				}			
			</script>
	</head>
	<body>
		<div>
				<a href="#">链接</a>
		</div>
	</body>
</html>

      他的顺序会是body->div->a

 

二  四种绑定方式

 

       前面我们看到了3种绑定方式,其实还有一种IE专用的。4种写法如下:

//跟html代码紧密结合,通用
第一种:<a href="#" onclick="doSomething()">链接</a>

//通用
第二种:domObj.onClick = function(){.......}

//IE专用
第三种:  domObj.attachEvent("onclick",function{}(.....));

//DOM标准,IE不支持
第四种:  domObj.addEventListener("click",function{}(.....), true/false);

      这4种写法中我们关心5个问题

1. 浏览器之间的通用性

2. 一个dom元素对同一个事件能否绑定多个事件

3. 是否支持冒泡跟捕获

4. this关键字是否指向dom元素

5. Event参数

 

      先来说说第5个问题吧,其实他只跟浏览器有关跟绑定方式无关,只有IE不提供Event参数,而作为window.Event提供。dom标准会为事件函数提供一个Event参数。

      至于第4个问题,只有第3种方式,也就是IE事件API它的this指针会指向window对象,其他的都指向当前dom元素.

      只有DOM标准才同时支持冒泡跟捕获两种模式,其余都仅支持冒泡

      第1,2种其实是一样的也称为传统的绑定方式,他们的通用性最好,但是不支持第2点即多绑。

 

三  模拟多绑

 

      因为传统方式有最好的通用性,明了的this指针。所以用实现通用的绑定方式且支持多绑相对于其他方式会方便很多。

Dean Edwards的addEvent库就是非常不错的一个方法。建议看的时候画它的数据结构,这样就很容易看懂了

function addEvent(element, type, handler){
	
	//为每一个事件处理函数绑定一个独立的ID
	if(!handler.$$guid) handler.$$guid = addEvent.guid++;
	//为元素建立一个事件类型的hash表
	if(!element.events) element.events = {};
	//为每对元素/事件建立一个事件处理函数
	var handlers = element.events[type];
	if(!handlers){
			handlers = element.events[type] = {};
			//已经绑定该类型事件
			if(element["on"+type]){
				handlers[0] = element["on"+type];
			}
	}
	//绑定该事件
	handlers[handler.$$guid] = handler;
	//需要一个全局事件处理函数处理所有事件
	element["on"+type] = handleEvent;

}
//ID计数器
addEvent.guid = 1;

function handleEvent(event){
	
	var returnValue = true;
	//获取事件对象(处理IE与DOM的不同)
	event = event || fixEvent(window.event);
	//获取事件类型处理函数列表
	var handlers = this.events[event.type];
	for(var i in handlers){
		this.$$handleEvent = handlers[i];
		if(this.$$handleEvent(event) === false){
			returnValue = false;
		}
	}
	return returnValue;
}

// 增加一些IE事件对象缺乏的方法
function fixEvent(event){
	event.preventDefault = fixEvent.preventDefault;
	event.stopPropagation = fixEvent.stopPropagation;
	return event;
}

fixEvent.preventDefault = function(){
	this.returnValue = false;
}

fixEvent.stopPropagation = function(){
	this.cancelBubble = true;
}

function removeEvent(element, type, handler){
	if(element.events && element.events[type]){
		delete element.events[type][handler.$$guid];
	}
}
 

四  模拟jQuery的事件写法

 

      在jQuery中事件写法通常是这样的:

$("...").click(function(){
     ......
});

      对照上面的addEvent这里的参数少了2个,一个是dom元素这个在jQuery对象内部,一个事件类型这里变成了函数名。还有一个问题是事件类型非常多,所以不可能用通常的方式为每个类型定义个函数。像上面的click函数应该就不存在显示的函数定义。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值