跳到主要内容

事件对象

在事件对象中,target 与 currentTarget 有什么不同?

target 属性指向的是事件目标,而 currentTarget 属性指向的是正在处理当前事件的对象,它总是指向事件绑定的元素。而 target 指向的可能不是定义时的事件目标。

例如:

div.addEventListener('click', (e) => {
console.log(e.target, e.currentTarget);
},false);

e.target 可能指向 div 元素,也可能指向它的子元素。而 e.currentTarget 总是指向 div 元素。

冒泡与捕获

事件冒泡与捕获是事件处理的两种机制,主要描述当在一个元素上有两个相同类型的事件处理器被激活会发生什么。

再点击子元素时,浏览器运行了两种不同的阶段:捕获阶段和冒泡阶段。捕获阶段的行为:

  • 浏览器检查元素的最外层祖先<html>,是否在捕获阶段中注册了一个onclick事件处理程序,如果是,则运行它;
  • 然后,它移动到<html>中单击元素的下一个祖先元素,并执行相同的操作,然后是单击元素再下一个祖先元素,依此类推,直到到达实际点击的元素;

而冒泡与捕获恰恰相反:

  • 浏览器检查实际点击的元素是否在冒泡阶段中注册了一个onclick事件处理程序,如果是,则运行它;
  • 然后它移动到下一个直接的祖先元素,并做同样的事情,然后是下一个,等等,直到它到达<html>元素;

而现代浏览器在默认情况下,所有事件处理程序都在冒泡阶段进行注册。因此上面代码在点击子元素时会先执行子元素绑定的事件,然后向上冒泡,触发父元素绑定的事件。

addEventListener 函数的第三个参数是个布尔值。含义:

  • 当布尔值是 false 时(这也是默认值),表示向上冒泡触发事件;
  • 当布尔值是 true 时,表示向下捕获触发事件;

不能冒泡的事件

有些事件是不会冒泡的。比如:

  • blur 元素失去焦点时触发,focusout 事件也是失去焦点时触发,但可以冒泡;
  • focus 元素获取焦点时触发;
  • mouseenter 鼠标移动到元素上时会触发该事件,与之对应的是 mouseover 事件,但会冒泡;
  • mouseleave 鼠标离开元素时触发,与之对应的是 mouseout,但会冒泡;

事件冒泡可以让我们利用事件委托,尤其是处理大量子元素时,如果给每个子元素都绑定事件,这是不优雅的,可以将事件绑定到父元素上,并让子结点上发生的事件冒泡到父结点上,利用 e.target 属性可以获取到当前触发事件的子元素。

事件对象中的方法

  • stopPropagation() 阻止事件冒泡,当设置后,点击该元素时父元素绑定的事件就不会再触发;
  • preventDefault() 阻止默认事件的发生;
  • stopImmediatePropagation() 它用来阻止监听同一事件的其他事件监听器被调用以及阻止事件冒泡,比如给同一个 div 元素绑定多个 click 事件(使用 addEventListener 方法可以注册多个),当在第二个事件函数中调用 stopImmediatePropagation 方法时,点击 div 元素时,后面注册的 click 将不会被触发,而且还会阻止事件冒泡;

在 IE 浏览器中,使用 e.cancelBubble = true 也可以取消事件冒泡;使用 e.returnValue = false 也能阻止默认事件的发生。