javascript事件解析(含兼容的事件类)

目标:能够了解javascript事件处理方式, 或得到事件兼容个浏览器的类
实现方式:代码及相关文字解释。
最后面有兼容所有浏览器支持的共用类。如果你急需用共用类,可先直接拿到该类用,等事后再看这篇文章,来了解各浏览器的兼容性原理。明白原理了完全可以自己写了。
首先拿出拿出来我们的实例html,以下所有javascript操作的都是这个html
<!DOCTYPE html>
<html>
<head>
<title>dom</title>
</head>
<body>
<input id="clickBtn" type="button" value="Click Me" />
<a id="link" href="www.google.com.hk">google</a>
</body>
<script type="text/javascript">
//这里面是我们放javascript代码的地方
 </script>
</html>
html事件处理程序
<input id="clickBtn" type="button" value="Click Me" οnclick="javascript:try{调用的方法}catch(e){}"/>
可能跟我们平常写的方法有出入,这么写的好处我一说就清楚了,当我们加载页面的时候,当我们html加载好了还没加载到我们的方法时候,点击,就会报错,我们这么写就可以避免了。
dom0级
var btn = document.getElementById("clickBtn");
btn.onclick = function(){
	alert(this.value);
}
btn.onclick = function(){
	alert(this.value+'2');
}
// Click Me2
这种事件赋值的方式,只能有一个onclick事件。后面的覆盖了前面的。删除事件就是 btn.onclick = null;
以这种处理方式是在事件的冒泡阶段被响应的。那什么是冒泡?
冒泡:就是当我们点击一个按钮时候,会从按钮的dom开始响应click事件直到document最外层dom。这个阶段是冒泡。这就好比我们在一张纸上画3个大小不同的同心圆,当我们拿手点最里面一个的圆心的时候,同时也点中了其他圆的圆心。这里冒泡的先后顺序就是从里到外。
捕获:这个跟冒泡相反,是从外到里的。也就是从document一层一层的找到最里面点击的dom。ie只支持冒泡,其他的浏览器同时支持两种,为什么讲这个?因为下面会涉及到这些基础知识。
事件监听器(dom2级事件处理)
好处,可以将事件注册在dom上,当触发时可以相应多个相同事件。这个有是兼容问题的,先讲讲标准,那就是非ie浏览器。addEventListener(); 和 removeEventListener();。
var btn = document.getElementById("clickBtn");
function handle(){
	alert(this.value);
}
function handle2(){
	alert(this.value+'2');
}
btn.addEventListener('click',handle,false);
btn.addEventListener('click',handle2,false);
btn.removeEventListener('click',handle,false);
你会好奇第三个参数是干什么的,为什么是false,其实这第三个函数就是判断是在冒泡阶段还是在捕获阶段响应该事件。false为冒泡阶段,前面说了ie是不支持捕获阶段的,我是为了兼容ie考虑的。下面来说说ie,对于ie没有上面两个方法,但是有另外两个对应的方法,那就是attachEvent() 和 detachEvent(),只在ie上有效的,所以别在非ie上测试这段代码哦!
var btn = document.getElementById("clickBtn");
function handle(){
	alert(this.value);
}
function handle2(){
	alert(this.value+'2');
}
btn.attachEvent('onclick',handle);
btn.attachEvent('onclick',handle2);
btn.detachEvent('onclick',handle2);
//undefined
这里attachEvent 和 detachEvent 少了一个参数,应为ie只支持冒泡所以就没有第三个参数了,还有一点注意的地方,这里的事件是 ‘onclick’ 而不是上面的 ‘click’。至于为什么打印出来的是undefined,看下面的例子:
var btn = document.getElementById("clickBtn");
function handle(){
	alert(this === window);//true
}
btn.attachEvent('onclick',handle);
在ie中这里面的this不再是btn对象而是window。所以为兼容考虑,里面最好就别用this了。至于用什么,稍后事件对象里会讲到。在这里我先做一个兼容性的事件监听器函数吧.
var EventUtil = {
	addHandler:function(element,event,handler){
		if(element.addEventListener){
			element.addEventListener(event,handler,false);
		}else if(element.attachEvent){
			element.attachEvent('on'+event,handler);
		}else{
			element['on'+event] = handler;
		}
	},
	removeHadler:function(element,event,handler){
		if(element.removeEventListener){
			element.removeEventListener(event,handler,false);
		}else if(element.detachEvent){
			element.detachEvent('on'+event,handler);
		}else{
			element['on'+event] = null;
		}
	}
}
很简单的方法,我们会在下面不断扩展的。
事件对象
按惯例,我们还是先看标准的浏览器的事件对象(非ie)。上面我们遗留了一个问题关于this的,这里我们换种思路一样都可以解决。
var btn = document.getElementById("clickBtn");
function handler(event){
	alert(event.type);//click
	alert(this === event.target);//true
	alert(this === event.currentTarget);//true
}
EventUtil.addHandler(btn,'click',handler);
我们来聊聊event.target 和 event.currentTarget 在这里他们都是指向this的,其实也有不同,this和event.currentTarget一定相同,因为这里他们指的是注册的元素,也就是我们传入的element,但是target指的是实际上的对象,比如下面这个例子:
var btn = document.getElementById("clickBtn");
function handler(event){
	alert(this === event.target);//false
	alert(this === event.currentTarget);//true
}
EventUtil.addHandler(document,'click',handler);
很清楚了,当我们点击按钮的时候,这里的event.currentTarget 和this 相等,因为都是指向的element即这里的document,而target指向的是实际的点击对象,即btn,所以不相等。在实际中我们更多用到的还是target。事件阻止函数,也可以叫默认事件取消函数,event.preventDefault();调用之后阻止接下来默认会发生的所有事件。甚至默认的事件,比如a标签的跳转。
var link = document.getElementById("link");
function prevent(event){
	event.preventDefault();
}
EventUtil.addHandler(document,'click',prevent);
点击的时候发现不会跳转了,同样的也可以阻止楚泽了的事件。
stopPropagation()可以阻止冒泡或者捕获事件在接下来的事件执行。比冒泡事件中我们点击页面上的btn,btn上注册的事件会执行,如果我们外层的document上一样的有相同事件注册,那么接着会触发document上的事件。用这个可以阻止掉。
var btn = document.getElementById("clickBtn");
function prevent(event){
	alert('prevent');
	event.stopPropagation();//去掉这一句就会冒泡到document
}
function handler(event){
	alert('handler');
}
EventUtil.addHandler(btn,'click',prevent);
EventUtil.addHandler(document,'click',handler);
下面来看看ie的事件对象。ie下同样有类似的方法,和属性。
首先看看event
var link = document.getElementById("link");
function handler(){
	alert(window.event);//object event
}
EventUtil.addHandler(document,'click',handler);
ie里面是不需要传参数的,当触发事件的时候,这个事件是在window上的所以直接调用window.event就能拿到event事件。target 就类似于ie中的ercElement, preventDefault 类似于ie中的returnValue = false; 阻止默认事件。
var link = document.getElementById("link");
function prevent(){
	window.event.returnValue = false;
}
EventUtil.addHandler(link,'click',prevent);
stopPropagation() 类似 ie中的cancelBubble = true; 但是ie中只能阻止冒泡,而非ie中可以阻止冒泡和捕获。
下面我们继续完善我们的兼容性时间注册类。
var EventUtil = {
	addHandler:function(element,event,handler){
		if(element.addEventListener){
			element.addEventListener(event,handler,false);
		}else if(element.attachEvent){
			element.attachEvent('on'+event,handler);
		}else{
			element['on'+event] = handler;
		}
	},
	removeHadler:function(element,event,handler){
		if(element.removeEventListener){
			element.removeEventListener(event,handler,false);
		}else if(element.detachEvent){
			element.detachEvent('on'+event,handler);
		}else{
			element['on'+event] = null;
		}
	},
	getEvent:function(event){
		return event ? event : window.event;
	},
	getTarget:function(event){
		return event.target ? event.target : event.srcElement;
	},
	preventDfault:function(event){
		if(event.preventDefault){
			event.preventDefault();
		}else{
			event.returnValue = false;
		}
	},
	stopPropagation:function(event){
		if(event.stopPropagation){
			event.stopPropagation();
		}else{
			event.cancelBubble = true;//注意这里是true
		}
	},
	getRelatedTarget:function(event){
		if(event.relatedTaget){
			return event.relatedTaget;
		}else if(event.toElement){
			return event.toElement;
		}else if(event.fromElement){
			return event.fromElement;
		}else{
			return null;
		}
	}
}
对于getRelatedTarget其实并不是这里要讲的内容,但由于很常用所以就加上去了,还有鼠标,键盘事件和浏览器事件兼容性这个会在以后补充上,暂时就写到这里,太长了,看的会累。当然如果能自己补充上,那样收获是最大的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值