您的位置:首页 > 其它

事件机制(事件冒泡与事件捕获)

2015-06-20 21:22 435 查看
<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><script type="text/javascript">
var pBtn=document.get
ElementById("inner");
pBtn.onclick=function(){
}
</script>


3、[b]DOM2级事件[/b]

  就是用addEventListener()等类型的,在事件处理上IE和DOM也是有区别的,

  IE中绑定事件和解绑为attachEvent(),detachEvent(),

  DOM中的为addEventListener(),removeEventListener()

  那么如何兼容此问题呢?如下代码,通过if..else类型判断

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>red</li>
<li>yellow</li>
<li>blue</li>
<li>green</li>
<li>black</li>
<li>white</li>
</ul>

如果点击页面中的li元素,然后输出li当中的颜色,我们通常会这样写:

(function(){
var color_list = document.getElementById('color-list');
var colors = color_list.getElementsByTagName('li');
for(var i=0;i<colors.length;i++){                          colors[i].addEventListener('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(oE[b]vent){[/b]

}

可用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生成的元素)所有的事件监测均能有效,且由于不用对多个元素进行事件绑定,能够有效的节省内存的损耗。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: