作者:ghost | 来源:互联网 | 2023-09-17 10:34
<div id="outer">
<p id="inner">Click me!p>
div>
事件冒泡
微软提出了名为事件冒泡(event bubbling)的事件流。时间冒泡就是指事件会从最内层的元素开始发生,一直向上传播,直到document对象。
因此上面的例子在事件冒泡的概念下发生click事件的顺序应该是p -> div -> body -> html -> document
事件捕获
网景提出另一种事件流名为事件捕获(event capturing)。与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
上面的例子在事件捕获的概念下发生click事件的顺序应该是document -> html -> body -> div -> p
Netscape Navigator不会将页面上的很多元素暴漏给事件
在DOM事件流中,“DOM2级事件”中规定的事件流同时支持了事件捕获阶段和事件冒泡阶段
穿插一个小片段,解释一下这里的dom2级事件。
使用事件处理程序有三种方式:
1、HTML事件处理程序
如:<div id="outer">
<p id="inner" Onclick="alert("我是html事件处理程序");">Click me!p>
div>
2、DOM0级事件处理程序
如:<div id="outer">
<p id="inner">Click me!p>
div>
3、DOM2级事件
就是用addEventListener()等类型的,在事件处理上IE和DOM也是有区别的,
IE中绑定事件和解绑为attachEvent(),detachEvent(),
DOM中的为addEventListener(),removeEventListener()
那么如何兼容此问题呢?如下代码,通过if..else类型判断
![](https://img1.php1.cn/3cd4a/24c6f/c5a/1eed59b003c6ecea.jpeg)
![](https://img1.php1.cn/3cd4a/24c6f/c5a/a23635f728ca17ac.jpeg)
<body>
<div id="box">
<input type="button" value="按钮" id="btn" onclick="showMes()">
<input type="button" value="按钮2" id="btn2">
<input type="button" value="按钮3" id="btn3">
<a href="event.html" id="go">跳转a>
div>
body>
html
![](https://img1.php1.cn/3cd4a/24c6f/c5a/1eed59b003c6ecea.jpeg)
![](https://img1.php1.cn/3cd4a/24c6f/c5a/a23635f728ca17ac.jpeg)
var eventUtil={
// 添加句柄
addHandler:function(element,type,handler){
if(element.addEventListener){
element.addEventListener(type,handler,false);
}else if(element.attachEvent){
element.attachEvent('on'+type,handler);
}else{
element['on'+type]=handler;
}
},
// 删除句柄
removeHandler: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){
return event?event:window.event;
},
getType:function(event){
return event.type;
},
getElement: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;
}
}
}
js
![](https://img1.php1.cn/3cd4a/24c6f/c5a/1eed59b003c6ecea.jpeg)
![](https://img1.php1.cn/3cd4a/24c6f/c5a/a23635f728ca17ac.jpeg)
window.Onload=function(){
var go=document.getElementById('go'),
box=document.getElementById('box');
eventUtil.addHandler(box,'click',function(){
alert('我是整个父盒子');
});
eventUtil.addHandler(go,'click',function(e){
//e=eventUtil.getEvent(e);
e=e || window.event;
alert(eventUtil.getElement(e).nodeName);
eventUtil.preventDefault(e);
eventUtil.stopPropagation(e);
});
}
js
应用例子:
<ul id="color-list">
<li>redli>
<li>yellowli>
<li>blueli>
<li>greenli>
<li>blackli>
<li>whiteli>
ul>
如果点击页面中的li元素,然后输出li当中的颜色,我们通常会这样写:
(function(){
var color_list = document.getElementById('color-list');
var colors = color_list.getElementsByTagName('li');
for(var i=0;i'click',showColor,false);
};
function showColor(e){
var x = e.target;
alert("The color is " + x.innerHTML);
};
})();
这样的代码再正常不过了,但是,如果页面上有几百个元素需要绑定(假设),那么务必就要绑定几百次啦。
这样问题就出现了:
第一:大量的事件绑定,性能消耗,而且还需要解绑(IE会泄漏)
第二:绑定的元素必须要存在
第三: 后期生成HTML会没有事件绑定,需要重新绑定
第四: 语法过于繁杂
在实际的开发当中,利用事件流的特性,我们可以使用一种叫做事件代理的方法。
利用事件流的特性,我们只绑定一个事件处理函数也可以完成:
(function(){
var color_list = document.getElementById('color-list');
color_list.addEventListener('click',showColor,false);
function showColor(e){
var x = e.target;
if(x.nodeName.toLowerCase() === 'li'){
alert('The color is ' + x.innerHTML);
}
}
})();
使用事件代理的好处不仅在于将多个事件处理函数减为一个,而且对于不同的元素可以有不同的处理方法。假如上述列表元素当中添加了其他的元素(如:a、span等),我们不必再一次循环给每一个元素绑定事件,直接修改事件代理的事件处理函数即可。
关于事件对象
在IE中事件对象是windows的一个属性event
oDiv.Onclick=function(){
var oEvent=window.event;
}
DOM标准则说,event对象必须作为唯一参数传给事件处理函数,
oDiv.Onclick=function(){
var oEvent=window.arguments【0】;
}
或者
oDiv.Onclick=function(oEvent){
}
可用event.type获取事件对象的类型
event.target获取事件对象的目标
event.stoppropagation()阻止冒泡
在Jquery中如何用呢?
具体来说,事件委托就是事件目标自身不处理事件,而是把处理任务委托给其父元素或者祖先元素,甚至根元素(document)
委托这么好的特性 jQuery 当然不会放过,所以就衍生出 .bind()、.live() .on()和.delegate(),jQuery 的事件绑定有多个方法可以调用,以 click 事件来举例:
click方法
bind方法
delegate方法
on方法
这里要清楚的认识:不管你用的是(click / bind / delegate)之中哪个方法,最终都是 jQuery 底层都是调用 on 方法来完成最终的事件绑定。因此从某种角度来讲除了在书写的方便程度及习惯上挑选,不如直接都采用 on 方法来的痛快和直接。
所以在新版的 API 中都这么写到:
.on()方法事件处理程序到当前选定的 jQuery 对象中的元素。在jQuery 1.7中,.on()方法提供绑定事件处理的所有功能、效果不言而喻了,除了性能的差异,通过委托的事件还能很友好的支持动态绑定,只要 on 的delegate 象是 HTML 页面原有的元素,由于是事件的触发是通过Javascript的事件冒泡机制来监测,所以对于所有子元素(包括后期通过JS生成的元素)所有的事件监测均能有效,且由于不用对多个元素进行事件绑定,能够有效的节省内存的损耗。