4

上个星期在微博中一个关于javascript捕获和冒泡代码的讨论,可能没有动手实现一篇的人无法给出确定的答案。

这里再来回顾一下之前的三条微博。

事件的执行顺序

JavaScript冒泡和捕获考察题目看图回答问题,晚上公布答案。

问:点击Li,JS的执行顺序是什么?

JavaScript捕获和冒泡探讨

总结就是:先捕获,后冒泡,捕获从上到下,冒泡从下到上(形象点说法:捕获像石头沉入海底,冒泡则像气泡冒出水面)

问:假如去掉注释 event.stopPropagation(); 结果又会输出什么?

答:去掉event.stopPropagation()
之后,由于事件有捕获和冒泡时先执行捕获,捕获到div之后,事件被阻止,后面就不在继续传播了。所以只输出divcallback.

在上面的代码如果增加一个div.addEventListener('click',callbackdiv2,false);

则div先执行捕获,接着执行上面这句冒泡,所以微博里的一个朋友评论说事件执行过捕获就不会执行冒泡其实是不对的。

div.addEventListener('click',callbackdiv,true);这一句只能是捕获才执行。

以上代码代码:演示

事件不同浏览器处理函数

element.addEventListener(type, listener[, useCapture]); // IE6~8不支持(捕获和冒泡通过useCapture,默认false)
element.attachEvent(’on’ + type, listener); // IE6~10,IE11不支持(只执行冒泡事件)
element[’on’ + type] = function(){} // 所有浏览器(默认执行冒泡事件)

JavaScript捕获和冒泡探讨

W3C规范中定义了3个事件阶段,依次是捕获阶段、目标阶段、冒泡阶段。事件对象按照上图的传播路径依次完成这些阶段。如果某个阶段不支持或事件对象的传播被终止,那么该阶段就会被跳过。举个例子,如果Event.bubbles属性被设置为false,那么冒泡阶段就会被跳过。如果Event.stopPropagation()在事件派发前被调用,那么所有的阶段都会被跳过。

捕获 阶段:

在事件对象到达事件目标之前,事件对象必须从window经过目标的祖先节点传播到事件目标。 这个阶段被我们称之为捕获阶段。在这个阶段注册的事件监听器在事件到达其目标前必须先处理事件。

目标 阶段:

事件对象到达其事件目标。 这个阶段被我们称为目标阶段。一旦事件对象到达事件目标,该阶段的事件监听器就要对它进行处理。如果一个事件对象类型被标志为不能冒泡。那么对应的事件对象在到达此阶段时就会终止传播。

冒泡 阶段:

事件对象以一个与捕获阶段相反的方向从事件目标传播经过其祖先节点传播到window。这个阶段被称之为冒泡阶段。在此阶段注册的事件监听器会对相应的冒泡事件进行处理。

在一个事件完成了所有阶段的传播路径后,它的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;
    }
  }
}

可以看我之前写过的一篇文章:如何停止冒泡和阻止默认行为

ps:半个月没发文章,因为我最近在搞这个:开发头条网,然后我发现这个东西做好和做坏根本没有出路,我考虑要不要下掉,呜呜……,请赐予我动力吧。


前端开发博客
713 声望100 粉丝

下一篇 »
jquery拖动代码