上个星期在微博中一个关于javascript捕获和冒泡代码的讨论,可能没有动手实现一篇的人无法给出确定的答案。
这里再来回顾一下之前的三条微博。
JavaScript冒泡和捕获考察题目看图回答问题,晚上公布答案。 问:点击Li,JS的执行顺序是什么?
总结就是:先捕获,后冒泡,捕获从上到下,冒泡从下到上(形象点说法:捕获像石头沉入海底,冒泡则像气泡冒出水面) 问:假如去掉注释 event.stopPropagation(); 结果又会输出什么?
答:去掉event.stopPropagation() 之后,由于事件有捕获和冒泡时先执行捕获,捕获到div之后,事件被阻止,后面就不在继续传播了。所以只输出divcallback.
在上面的代码如果增加一个div.addEventListener('click',callbackdiv2,false); 则div先执行捕获,接着执行上面这句冒泡,所以微博里的一个朋友评论说事件执行过捕获就不会执行冒泡其实是不对的。 div.addEventListener('click',callbackdiv,true);这一句只能是捕获才执行。
以上代码代码:演示
W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段。事件对象按照上图的传播路径依次完成这些阶段。如果某个阶段不支持或事件对象的传播被终止,那么该阶段就会被跳过。举个例子,如果Event.bubbles
属性被设置为false
,那么冒泡阶段就会被跳过。如果Event.stopPropagation()
在事件派发前被调用,那么所有的阶段都会被跳过。
在一个事件完成了所有阶段的传播路径后,它的Event.currentTarget
会被设置为null
并且Event.eventPhase
会被设为0。Event
的所有其他属性都不会改变(包括指向事件目标的Event.target
属性).
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) { // DOM2
element.addEventListener(type, handler, false);
} else if (element.attachEvent) { // IE
element.attachEvent('on' + type, handler);
} else { // DOM0
element['on' + type] = handler;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent('on' + type, handler);
} else {
element['on' + type] = null;
}
}
};
var EventUtil = {
getEvent: function(e) {
return e ? e : window.e;
},
getTarget: function(e) {
return e.target || e.srcElement;
},
preventDefault: function(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
},
stopPropagation: function(e) {
if (e.stopPropagation) {
e.stopPropagation()
} else {
e.cancelBubble = true;
}
}
}
可以看我之前写过的一篇文章:如何停止冒泡和阻止默认行为