二级事件模型
全部代码:
<!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(); // 阻止事件冒泡 });