Js事件流

CONTENTS
  • DOM事件流
  • 事件冒泡
  • 阻止冒泡
  • 事件捕获


DOM事件流

1.什么是事件流?

事件流所描述的是从页面中接受事件的顺序

2.DOM事件流的三个阶段?

事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

3.DOM事件流三个阶段的执行顺序?

首先发生的事件捕获,为截取事件提供机会,然后是目标接受事件,最后是事件冒泡阶段,所以可以在最后一个阶段对事件作出响应。见下图更直观:


          在dom事件流中,事件的目标在捕获阶段不会接受到事件,这意味着在捕获阶段,事件从 document 到 div 后就停止了。下一个阶段是目标阶段,于是事件在 div 上发生,并在事件处理中被看成是冒泡阶段的一部分, 然后,冒泡阶段发生,事件又传回document。


事件冒泡

1.什么是事件冒泡?
当事件发生后,这个事件就要开始传播(从里向外或者从外向里)

2.为什么要传播?

因为事件源本身(可能)并没有处理事件的能力,即处理事件的函数(方法)并未绑定在该事件源上。例如我们点击一个按钮时,就会产生一个click事件,但这个按钮本身可能不能处理这个事件,事件必须从这个按钮传播出去,从而到达能够处理这个事件的代码中(例如我们给按钮的onclick属性赋一个函数的名字,就是让这个函数去处理该按钮的click事件),或者按钮的父级绑定有事件函数,当该点击事件发生在按钮上,按钮本身并无处理事件函数,则传播到父级去处理。

小案例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>Document</title>
</head>
<body>
    <div>
        <button>点击</button>
    </div>
</body>
</html>
复制代码

当我们点击按钮button时,事件时这样传播的:

(1) button

(2) div

(3) body

(4) html

(5) document


阻止冒泡

1.为什么要阻止冒泡?

例如:document上有A事件,div有B事件,div里面的span有C事件,如果不给span和div加阻止事件冒泡的话,点击span时就会触发到div的B事件、document的A事件,当点击span时不想触发div和document的事件就要加上阻止事件冒泡,div也是一样的道理,如果我们不想让点击某个事件时父级受到影响,这时就应阻止冒泡。

eg:不加阻止冒泡事件,代码如下:

css代码:

   <style type="text/css">
        .box1{width:200px;height:200px;background:pink;}
        .box2{width:100px;height:100px;background:gray;}
    </style>复制代码

​js+html代码:

<body>
    <div class="box1">
        <div class="box2"></div>
    </div>
    <script type="text/javascript">
        //获取对象
        var box1 = document.getElementsByClassName('box1')[0];
        var box2 = document.getElementsByClassName('box2')[0];
        //添加事件
        box1.onclick = function(){
            console.log('您点击了box1');
        }
        box2.onclick = function(){
            console.log('您点击了box2');
        }
    </script>
</body>复制代码

效果如下:


如图可以看出当点击 box1 时,只会提示‘您点击了box1’ 而点击 box2 时,竟然输出了两句提示,如果我们不想要这种效果,我们只想要在点击了哪个按钮后就执行该按钮的命令,也就是说阻止冒泡。

下面给出上述小案例的阻止冒泡方法:一句代码搞定,改变 box2 的触发事件,代码如下:

box2.onclick = function(e){
            console.log('您点击了box2');
            e.stopPropagation();
        }复制代码

效果图如下:这样就实现阻止冒泡


2.阻止冒泡的方法。

event.stopPropagation()方法 (这个方法小编在上面已经给出了例子,这里就不在给出具体的例子)

这是阻止事件的冒泡方法,不让事件向documen上蔓延,但是默认事件仍然会执行,当你调用这个方法的时候,如果点击一个连接,这个连接仍然会被打开,

event.preventDefault()方法

这是阻止默认事件的方法,调用此方法是,连接不会被打开,但是会发生冒泡,冒泡会传递到上一层的父元素;

下面给大家一个小例子:看图说话,在下面的空白处,无论我怎么点击右键,无论在什么位置点击,都会出现默认的东西,如果我们不想要这种默认的东西怎么办呢?继续看图下面的案例,马上带你飞,走起-------


eg:阻止浏览器右键默认事件

css代码:

<style type="text/css">
        *{margin:0;padding:0;}
        ul{list-style:none;}
        .box{position:relative;width:80px;border:1px solid gray;display: none;}
        .box  ul li{height:40px;line-height:40px;text-align:center;}
        .box  ul li:hover{background:#ccc;}
    </style>复制代码

 html+js代码:

<body>
  <div class='box'>
      <ul>
          <li>刷新</li>
          <li>删除</li>
          <li>命名</li>
      </ul>
  </div>
  <script type="text/javascript">
      //获取box对象
      var  box = document.getElementsByClassName('box')[0];
      //右键鼠标事件
      window.oncontextmenu = function(event){
        //阻止默认事件
        event.preventDefault();
        //获取鼠标点击某个位置的水平位置  X  和垂直位置   Y
        var  x=event.clientX;
        var  y=event.clientY;
        //改变 box 距离上面和左边的位置
        box.style.top = y + 'px';
        box.style.left = x + 'px';
        box.style.display = 'block';
      }
        window.onclick = function() {
            box.style.display = "none";
        }
  </script>
</body>
复制代码

效果如下:


return false(这里的例子就不赘述了,有心的小伙伴可以动手试试)

这个方法比较暴力,他会同时阻止事件冒泡也会阻止默认事件;写上此代码,连接不会被打开,事件也不会传递到上一层的父元素;可以理解为return false就等于同时调用了event.stopPropagation()和event.preventDefault()


事件捕获

事件捕获和事件冒泡是刚好相反的,事件捕获是指不太具体的节点应该更早的接收到事件,而最具体的节点应该最后接收到事件

案例走起:

css代码:

<style type="text/css">
        .box1{width:300px;height:300px;background:pink;}
        .box2{width:200px;height:200px;background:skyblue;}
        .box3{width:100px;height:100px;background:gray;}
    </style>复制代码

html+js代码:

​<body>    <div class="box1">
        <div class="box2">
            <div class="div box3"></div>
        </div>
    </div>
    <script type="text/javascript">
        //获取对象
        var box1 = document.getElementsByClassName('box1')[0];
        var box2 = document.getElementsByClassName('box2')[0];
        var box3 = document.getElementsByClassName('box3')[0];
        //点击事件
        box1.addEventListener('click',function(){
            console.log("捕获 box1");
        },true);
        box2.addEventListener('click',function(){
            console.log("捕获 box2");
        },true);
        box3.addEventListener('click',function(){
            console.log("捕获 box3");
        },true);

    </script>
</body>复制代码

动态效果如下:


当我点击最里面的 box3 时,我们可以看到最外层的事件先被触发,最后才是我们点击的 box3 事件被触发,这便是事件捕获。 

转载于:https://juejin.im/post/5b4f23685188251afc257668

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值