一个事件发生后,会在子元素和父元素之间传播。这种传播分成三个阶段。
window→documen→...→目标节点 第一阶段:捕获阶段,从window对象传导到目标节点 第二阶段:目标阶段,事件在目标节点上触发 第三阶段:冒泡阶段,从目标节点传回window对象 IE678的事件模型只有冒泡阶段。
总结:"DOM2级事件"规定事件流的三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会;然后是实际的目标接收到事件;最后一个阶段是冒泡阶段,可以在这个阶段对事件作出响应,即:事件捕获->事件处理->事件冒泡
阻止事件冒泡
event.stopPropagation() stopImmediatePropagation方法阻止同一个事件的其他监听函数被调用,不管监听函数定义在当前节点还是其他节点。也就是说,该方法阻止事件的传播,比Event.stopPropagation()更彻底。 event.stopImmediatePropagation() event.cancelBubble() IE阻止事件冒泡
事件委托原理:事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul>li;比如给最里面的li加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul,li做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。
案例:
<ul id="ul"> <li>aa</li> <li>bb</li> <li>cc</li> </ul> <script> window.onload = function(){ var oUl = document.getElementById("ul"); oUl.onclick = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; if(target.nodeName.toLowerCase() == 'li'){ console.log(target.innerHTML); } } } </scropt>
事件捕获->事件处理->事件冒泡,父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会触发,当然,这里当点击ul的时候,也是会触发的,怎么只有点击li才会触发呢. Event对象提供了一个属性叫target,可以返回事件的目标节点,我们成为事件源,也就是说,target就可以表示为当前的事件操作的dom,但是不是真正操作dom,当然,这个是有兼容性的,标准浏览器用ev.target,IE浏览器用event.srcElement,此时只是获取了当前节点的位置,并不知道是什么节点名称,这里我们用nodeName来获取具体是什么标签名
事件委托优点: 1. 只在内存中开辟了一块空间,节省资源同时减少了dom操作,提高性能 2. 对于新添加的元素也会有之前的事件
总结:什么样的事件可以用事件委托,什么样的事件不可以用呢? 适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。 不适合的就有很多了,举个例子,mousemove,mouseout,每次都要计算它的位置,非常不好把控,在不如说focus,blur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。