JS 事件机制

344 阅读2分钟

DOM事件流(event flow )存在三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。

事件捕获

当触发dom事件时,浏览器会从根节点开始由外到内进行事件传播

即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。

事件冒泡

与事件捕获相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。

无论是事件捕获还是事件冒泡,它们都有一个共同的行为,就是事件传播

dom标准事件流的触发顺序

先捕获再冒泡,即当触发dom事件时,会先进行事件捕获,捕获到事件源之后通过事件传播进行事件冒泡。不同的浏览器对此有着不同的实现,IE10及以下不支持捕获型事件,所以就少了一个事件捕获阶段,IE11、Chrome 、Firefox、Safari等浏览器则同时存在。

两个用于事件绑定的方法

addEventListener(event, listener, useCapture)

参数定义:

  • event——(事件名称,如click,不带on)
  • listener——事件监听函数,
  • useCapture——是否采用事件捕获进行事件捕捉,默认为false,即采用事件冒泡方式

addEventListener在 IE11、Chrome 、Firefox、Safari等浏览器都得到支持。

attachEvent(event,listener)

参数定义:

  • event---(事件名称,如onclick,带on),
  • listener---事件监听函数。

attachEvent主要用于IE浏览器,并且仅在IE10及以下才支持,IE11已经废了这个方法了

实例1:(事件冒泡)
<div id="parent">父元素
	<div id="child">子元素</div>
</div>
<script type="text/javascript">
    var parent = document.getElementById("parent");
    var child = document.getElementById("child");
    document.body.addEventListener("click", function (e) {
      console.log("body");
    }, false);
    parent.addEventListener("click", function (e) {
      console.log("parent");
    }, false);
    child.addEventListener("click", function (e) {
      console.log("child");
      e.stopPropagation(); =>此行代码作用为阻止事件冒泡;即点击子元素不想触发父元素的事件
    }, false);
</script>
<!--采用事件冒泡方式给dom元素注册click事件
点击子元素后代码输出顺序 child->parent->body
-->
附:阻止事件冒泡
w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true
取消事件默认行为
w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;
实例2:(事件捕获)
//在例1的基础上做以下修改
parent.addEventListener("click", function (e) {
  console.log("click-parent---事件传播");
}, false);
//新增事件捕获事件代码 
parent.addEventListener("click", function (e) {
  console.log("click-parent--事件捕获");
}, true);
child.addEventListener("click", function (e) {
  console.log("click-child");
}, false);
//点击子元素的输出为:
//click-parent--事件捕获 =》click-child =》click-parent---事件传播 =》click-body
//点击父元素时:
//click-parent---事件传播 =>click-parent--事件捕获 =>click-body
//父元素通过事件捕获的方式注册了click事件,所以在事件捕获阶段就会触发,然后到了目标阶段,即事件源,之后进行事件传播,parent同时也用冒泡方式注册了click事件,所以这里会触发冒泡事件,最后到根节点。这就是整个事件流程。