事件流

   日期:2020-11-01     浏览:83    评论:0    
核心提示:文章目录前言一、以前两种事件流分析1.冒泡事件流2.捕获事件流结合:二、JS事件流1.原理1.on属性问题:2.addEventLIstener()问题三、阻止事件传递1.Event.stopPropagation() 方法2.Event.stopImmediatePropagation()方法3.cancelBubble前言JS事件流问题也可以理解为事件触发顺序问题,而JS事件流最早要从IE和网景公司的浏览器大战说起,当浏览器发展到第四代时,IE提出的是冒泡流,而网景提出的是捕获流,两种事件流形式

文章目录

  • 前言
  • 一、以前两种事件流分析
    • 1.冒泡事件流
    • 2.捕获事件流
    • 结合:
  • 二、JS事件流
    • 1.原理
      • 1.on属性问题:
      • 2.addEventLIstener()问题
  • 三、阻止事件传递
    • 1.Event.stopPropagation() 方法
    • 2.Event.stopImmediatePropagation()方法
    • 3.cancelBubble

前言

JS事件流问题也可以理解为事件触发顺序问题,而JS事件流最早要从IE和网景公司的浏览器大战说起,当浏览器发展到第四代时,IE提出的是冒泡流,而网景提出的是捕获流,两种事件流形式完全相反。

一、以前两种事件流分析

1.冒泡事件流

个人理解是和冒泡排序原理相似,即事件有最具体的接收,之后逐渐向上冒泡,传到页面。(即由子元素逐渐向父元素传)
以button按钮为例:

2.捕获事件流

与冒泡事件流原理完全相反,事件从页面元素开始接收,逐级向下到最具体的元素。
同样以button按钮为例:

结合:

后来在W3C组织的统一之下,JS支持了冒泡流和捕获流,两种事件流在DOM2级事件中得到了统一,相对于DOM0事件类型,DOM2级有以下特点:

  1. 允许某个元素绑定多个同类型事件(可以拿addEventLIstener事件与on事件为例)。
  2. 规定了事件流的三个阶段:捕获阶段,目标阶段,冒泡阶段。
    注意用Event.eventPhase可以返回当前所在的阶段:
var phase = event.eventPhase;

0,事件目前没有发生。
1,事件目前处于捕获阶段,即处于从祖先节点向目标节点的传播过程中。
2,事件到达目标节点,即Event.target属性指向的那个节点。
3,事件处于冒泡阶段,即处于从目标节点向祖先节点的反向传播过程中。

二、JS事件流

1.原理

JS事件的原理图如下:


由图可知:

  1. 现在的JS事件流是由捕获事件流和冒泡事件流组合形成的,即由window开始最后回到window的过程。
  2. 事件流被分为三个阶段(1-5)捕获过程、(5-6)目标过程、(6~10)冒泡过程。
  3. 这个过程决定了事件点击时的执行顺序。

1.on属性问题:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div style="width:200px;height:200px;background:lightblue" id="content">
        <button style="width:100px;height:50px;" id="btn1">
        </button>
    </div>
</body>
<script type="text/javascript">
    var content = document.getElementById("content");
    var btn1 = document.getElementById('btn1');
    btn1.onclick = function(){ 
        alert("button");
    };
    content.onclick = function(){ 
        alert("content");
    }
    //点击button的结果是先打印button之后再打印content
</script>
</html>

由执行结果可知,on-属性的执行是在冒泡阶段发生的,对于EventTarget.addEventListener()的原理也是一样的。

2.addEventLIstener()问题

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset = "UTF-8">
    <title>Document</title>
</head>
<body>
    <div style = "width:200px;height:200px;background:lightblue" id="content">
        <button style = "width:100px;height:50px;" id="btn1">
        </button>
    </div>
</body>
<script type = "text/javascript">
    var content = document.getElementById("content");
    var btn1 = document.getElementById('btn1');
   btn1.addEventListener('click', function () {   alert("button的冒泡阶段"); }, false);
   btn1.addEventListener('click', function () {   alert("button的捕获阶段"); }, true);
   content.addEventListener('click', function () {   alert('content的冒泡阶段'); }, false);
   content.addEventListener('click', function () {   alert('content的捕获阶段'); }, true);
   //结果为:content的捕获阶段
   // button的冒泡阶段
   // button的捕获阶段
   // content的冒泡阶段
</script>
</html>

注意EventTarget.addEventListener()监听函数useCapture值为false时表示只在冒泡阶段被触发

三、阻止事件传递

通过之前的描述可以轻易看出,事件流中某元素被触发之后会造成连锁反应:会导致其容器元素同类型的事件被触发,有时候,这并不是我们所需要的所以,我们需要进行阻止。

1.Event.stopPropagation() 方法

stopPropagation()方法可以阻止事件在 DOM 中继续传播,防止再触发定义在别的节点上的监听函数,但是不包括在当前节点上其他的事件监听函数。
上代码:

function stopEvent(e) { 
  e.stopPropagation();
}

el.addEventListener('click', stopEvent, false);

此时,click事件将不会进一步冒泡到el节点的父节点。

2.Event.stopImmediatePropagation()方法

此方法与之前的方法最大的区别在于其阻止的更加彻底,可以阻止同一个事件的其他监听函数被调用,不管监听函数定义在当前节点还是其他节点。
如果同一个节点对于同一个事件指定了多个监听函数,这些函数会根据添加的顺序依次调用。只要其中有一个监听函数调用了Event.stopImmediatePropagation()方法,其他的监听函数就不会再执行了。
上代码:

function l1(e){ 
  e.stopImmediatePropagation();
}

function l2(e){ 
  console.log('hello world');
}

el.addEventListener('click', l1, false);
el.addEventListener('click', l2, false);

上面代码在el节点上,为click事件添加了两个监听函数l1和l2。由于l1调用了event.stopImmediatePropagation方法,所以l2不会被调用。

3.cancelBubble

cancelBubble是IE标准下阻止事件传递的属性,设置cancelBubble=true表示阻止冒泡。
它与stopPropagation()兼容性对比如下:

所以,注意:

  1. 若需要在捕获阶段阻止事件传递,使用addEventListener()进行事件监听,同时使用e.stopPropagation()阻止冒泡。
  2. 若需要在冒泡阶段阻止事件传递,在兼容addEventListener()和attachEvent()的同时,为保险起见,需要对阻止事件传递方式进行兼容。以下仅表示在DOM2及事件模型下兼容方式:
if (e.stopPropagation){ 
      e.stopPropagation();
  }else{ 
      e.cancelBubble = true;
  }
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服