二级事件模型
全部代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>二级事件模型</title>
<style>
p, li {
line-height: 150%;
}
div {
padding: 10px 5px;
}
.ul {
width: 50%;
background: #ccc;
padding: 30px;
margin: 0;
}
.ul li {
margin: 15px;
background: #84cf39;
color: #fff;
list-style: none;
padding: 5px;
}
</style>
<script type="text/javascript">
var $ = function(elmID){
return document.getElementById(elmID);
}
var getNodeName = function(e){
var e = e || window.event;
return e.toElement.nodeName;
}
window.onload = function(){
var ul = $('eventUl');
var result = $('result').getElementsByTagName('span')[0];
var attachEventName = window.addEventListener ? 'addEventListener' : 'attachEvent';
var mouseoverName = window.addEventListener ? 'mouseover' : 'onmouseover';
var fn1 = function(e){
result.innerHTML += ' <br/>绑定在ul上的mouseover,事件的触发来自' + getNodeName(e) + '标签(冒泡),';
}
var fn2 = function(e){
result.innerHTML += ' <br/>绑定在ul上的mouseover,事件的触发来自' + getNodeName(e) + '标签(捕获),';
}
ul[attachEventName](mouseoverName, fn1);
ul[attachEventName](mouseoverName, fn2, true);
var lis = ul.getElementsByTagName('li');
var fn3 = function(e){
result.innerHTML += ' <br/>绑定在li上的mouseover,终止向上冒泡(冒泡),';
if (e) {
e.stopPropagation();
}
else {
window.event.cancelBubble = true;
}
}
var fn4 = function(e){
result.innerHTML += ' <br/>LI事件的捕获,';
if (e) {
e.stopPropagation();
}
else {
window.event.cancelBubble = true;//IE的享元模式
}
}
lis[0][attachEventName](mouseoverName, fn3, false);
};
</script>
</head>
<body>
<div>
<p>
先通过demo展示: 为ul分别绑定mouseover的捕获与冒泡事件,为第一个li绑定mouseover的冒泡事件,并终止向上冒泡(stopPropagation)
</p>
</div>
<div>
Demo:
</div>
<ul class="ul" id="eventUl">
<li>
第一条(不再向上冒泡)
</li>
<li>
第二条
</li>
<li>
第三条
</li>
</ul>
<div id="result">
监听结果:<span></span>
</div>
<div>
<p>
当鼠标移到灰色区域(ul),再逐渐移到第一条绿色区域(li),再移回到灰色区域 就会看到有意思的一组记录了。
</p>
<p>
绑定在ul上的mouseover,事件的触发来自UL标签(冒泡),
绑定在ul上的mouseover,事件的触发来自UL标签(捕获),
<br/>
绑定在ul上的mouseover,事件的触发来自LI标签(捕获),
绑定在li上的mouseover,终止向上冒泡(冒泡),
<br/>
绑定在ul上的mouseover,事件的触发来自UL标签(冒泡),
绑定在ul上的mouseover,事件的触发来自UL标签(捕获),
</p>
<p>
当然还可以从灰色区域(ul)移到第二条绿色区域(li)看一下向上冒泡的展示结果,下面是相关的原理解释(关于浏览器兼容处理细节就查看源代码吧):
</p>
<ul>
<li>
二级事件模型:
<br/>
[document -> <body> -> ... ->] [<a;></a>] [ -> ... -> <body> -> document]
<br/>
[捕获] -> [命中] -> [冒泡]
</li>
<li>
事件监听的最后一个参数可选,不传默认是false冒泡,true绑定捕获。
</li>
<li>
浏览器支持情况良好,我测试了IE6和chrome都符合上面事件模型,但是事件的监听和事件参数的处理需要做兼容性处理。
非IE:队列式,addEventListener,removeEventListener,事件无on ---- IE:堆栈式,attachEvent,detachEvent,事件有on
</li>
<li>
在命中的元素上,高级浏览器(chrome,IE9等)先触发冒泡再触发捕获,而IE6,7,8则是先捕获后冒泡,这个现象我个人觉得比较奇怪。
</li>
<li>
鼠标从内层元素一道外层元素时任然会触发外层元素的监听事件。
</li>
<li>
事件的向上冒泡可以用e.stopPropagation()或window.event.cancelBubble = true来终止事件向上冒泡。
</li>
</ul>
<p>
</p>
</div>
</body>
</html>
原理介绍(如果要验证原理的正确性,可以直接运行上面代码):
先通过demo展示: 为ul分别绑定mouseover的捕获与冒泡事件,为第一个li绑定mouseover的冒泡事件,并终止向上冒泡(stopPropagation)。

监听结果:
当鼠标移到灰色区域(ul),再逐渐移到第一条绿色区域(li),再移回到灰色区域 就会看到有意思的一组记录了。
绑定在ul上的mouseover,事件的触发来自UL标签(冒泡), 绑定在ul上的mouseover,事件的触发来自UL标签(捕获),
绑定在ul上的mouseover,事件的触发来自LI标签(捕获), 绑定在li上的mouseover,终止向上冒泡(冒泡),
绑定在ul上的mouseover,事件的触发来自UL标签(冒泡), 绑定在ul上的mouseover,事件的触发来自UL标签(捕获),
当然还可以从灰色区域(ul)移到第二条绿色区域(li)看一下向上冒泡的展示结果,下面是相关的原理解释(关于浏览器兼容处理细节就查看源代码吧):
- 二级事件模型:
[document -> <body> -> ... ->] [<a;></a>] [ -> ... -> <body> -> document]
[捕获] -> [命中] -> [冒泡] - 事件监听的最后一个参数可选,不传默认是false冒泡,true绑定捕获。
- 浏览器支持情况良好,我测试了IE6和chrome都符合上面事件模型,但是事件的监听和事件参数的处理需要做兼容性处理。 非IE:队列式,addEventListener,removeEventListener,事件无on ---- IE:堆栈式,attachEvent,detachEvent,事件有on
- 在命中的元素上,高级浏览器(chrome,IE9等)先触发冒泡再触发捕获,而IE6,7,8则是先捕获后冒泡,这个现象我个人觉得比较奇怪。
- 鼠标从内层元素一道外层元素时任然会触发外层元素的监听事件。
- 事件的向上冒泡可以用e.stopPropagation()或window.event.cancelBubble = true来终止事件向上冒泡。
jq停止向上冒泡:
$('span').bind("click",function(event){
var txt = $('#msg').html() + "<p>内层span元素被点击.<p/>";
$('#msg').html(txt);
event.stopPropagation(); // 阻止事件冒泡
});
浙公网安备 33010602011771号