事件冒泡
事件冒泡:事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播。例如当用户点击了<div>元素,click事件将按照<div>—><body>—><html>—>document的顺序进行传播。若在<div>和<body>上都定义了click事件,则在冒泡过程中会依次触发事件。如下:
<script type="text/javascript"> var div=document.getElementById("myDiv"); div.onclick=function(event){ alert("div"); }; document.body.onclick=function(event){ alert("body"); }; </script>
点击<div>,将先输出“div”,再输出“body”。
IE9,chrome,Firefox,Opera,Safari都支持事件冒泡,并将事件冒泡到window对象。
事件捕获
事件捕获是先由最上一级的节点先接收事件,然后向下传播到具体的节点。当用户点击了<div>元素,采用事件捕获,则click事件将按照document—><html>—><body>—><div>的顺序进行传播。
若在<div>和<body>上都定义了click事件,如下:
<script type="text/javascript"> var div=document.getElementById("myDiv"); div.addEventListener("click",function(event){ alert("div"); },true); document.body.addEventListener("click",function(event){ alert("body"); },true); </script>
点击<div>,将先输出“body”,再输出“div”。
IE9,chrome,Firefox,Opera,Safari都支持事件捕获,但是IE8和IE8以下的版本只支持事件冒泡。尽管DOM2规范要求事件应该从document对象开始传播,但是现在的浏览器实现都是从window对象开始捕获事件。
DOM事件流:
结合上述,兼备捕获和冒泡,先捕获后冒泡。
事件委托
一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。
<ul id="line"> <li></li> <li></li> <li></li> <li></li> <!--不定数个li--> <li></li> <li></li> </ul>
若要实现点击li标签,对应的li就会消失,只需把事件绑定在ul上,代码如下,
//找到父元素,添加监听器 document.getElementById("line").addEventListener("click",function (ev) { // ev.target是被点击元素 // 如果被点击的是li元素 if(ev.target&&ev.target.nodeName=="LI") { ev.target.remove(); } })
selectorString
是个css选择器字符串.举个例子,ev.target.matches(‘li.li1‘)。如果 target 元素是标签 li 并且它的类是 li1 ,那么就会返回 true,否则返回 false;当然它的兼容性还有一些问题,需要 IE9 及以上的现代化浏览器版本;
我们可以使用 Polyfill 来解决兼容性上的问题:
if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function(s) { var matches = (this.document || this.ownerDocument).querySelectorAll(s), i = matches.length; while (--i >= 0 && matches.item(i) !== this) {} return i > -1; }; }
加上 Element.matches 之后就可以来实现我们的需求了:
jQuery 中的事件委托
jQuery 中的事件委托相信很多人都用过,它主要这几种方法来实现:
- $.on: 基本用法: $(‘.parent‘).on(‘click‘, ‘a‘, function () { console.log(‘click event on tag a‘); }),它是 .parent 元素之下的 a 元素的事件代理到 $(‘.parent‘) 之上,只要在这个元素上有点击事件,就会自动寻找到 .parent 元素下的 a 元素,然后响应事件;
- $.delegate: 基本用法: $(‘.parent‘).delegate(‘a‘, ‘click‘, function () { console.log(‘click event on tag a‘); }),同上,并且还有相对应的 $.delegate 来删除代理的事件;