面试题7:Js事件流,事件冒泡(IE事件流)

122 篇文章 11 订阅

事件流

在第四代 Web 浏览器(IE4 和 Netscape Communicator 4)开始开发时,开发团队碰到了一个有意思的问题:页面哪个部分拥有特定的事件呢?要理解这个问题,可以在一张纸上画几个同心圆。把手指放到圆心上,则手指不仅是在一个圆圈里,而且是在所有的圆圈里。两家浏览器的开发团队都是以同样的方式看待浏览器事件的。当你点击一个按钮时,实际上不光点击了这个按钮,还点击了它的容器以及整个页面。

事件流描述了页面接收事件的顺序。结果非常有意思,IE 和 Netscape 开发团队提出了几乎完全相反的事件流方案。IE 将支持事件冒泡流,而 Netscape Communicator 将支持事件捕获流。

事件冒泡(IE事件流)

IE 事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。

面试官:什么是事件冒泡

例如:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    *{
      color: white;
      font-size: 20px;
    }
    #outer{
      width: 300px;
      height: 300px;
      background-color: red;
    }
    #center{
      width: 200px;
      height: 200px;
      background-color: blue;
    }
    #inner{
      width: 100px;
      height: 100px;
      background-color: green;
    }
  </style>
</head>
<body>
  <div id="outer">outer
    <div id="center">center
      <div id="inner">inner</div>
    </div>
  </div>
  <script>
    var inner = document.getElementById('inner');
    var center = document.getElementById('center');
    var outer = document.getElementById('outer');
    // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样
    inner.onclick = function () {
      console.log('我是inner点击的');
    }
    // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象
    center.onclick = function () {
      console.log('我是center点击的');
    }
    outer.onclick = function () {
      console.log('我是outer点击的');
    }
  </script>
</body>
</html>

 效果:

点击inner之后会输出inner,和后面父级的center、outer

在点击页面中的id为inner的div元素,click事件会以如下顺序发生

由内向外

  1. div#inner

  2. div#center

  3. div#outer

  4. body

  5. html

  6. document

也就是说,div#inner元素,即被点击的元素,最先触发 click 事件。然后,click 事件沿DOM 树一路向上,在经过的每个节点上依次触发,直至到达 document 对象。

所有现代浏览器都支持事件冒泡,只是在实现方式上会有一些变化。IE5.5及早期版本会跳过html元素(从body直接到 document)。现代浏览器中的事件会一直冒泡到 window 对象。

阻止事件冒泡

使用阻止事件冒泡之前,先要知道DOM事件默认提供的一个对象,HTML DOM Event对象。

Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。

事件通常与函数结合使用,函数不会在事件发生前被执行!

event.stopPropagation()

直接在对应方法中使用event.stopPropagation()便可阻止事件冒泡。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    *{
      color: white;
      font-size: 20px;
    }
    #outer{
      width: 300px;
      height: 300px;
      background-color: red;
    }
    #center{
      width: 200px;
      height: 200px;
      background-color: blue;
    }
    #inner{
      width: 100px;
      height: 100px;
      background-color: green;
    }
  </style>
</head>
<body>
  <div id="outer">outer
    <div id="center">center
      <div id="inner">inner</div>
    </div>
  </div>
  <script>
    var inner = document.getElementById('inner');
    var center = document.getElementById('center');
    var outer = document.getElementById('outer');
    // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样
    inner.onclick = function (event) {
      console.log('我是inner点击的');
      //阻止事件冒泡
      event.stopPropagation();
    }
    // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象
    center.onclick = function () {
      console.log('我是center点击的');
    }
    outer.onclick = function () {
      console.log('我是outer点击的');
    }
  </script>
</body>
</html>

效果:

点击inner之后只会输出inner,而后面父级的不会输出center、outer了

 

注意:如果点击方法时需要同时传递其他参数和event,直接传递event这个单词即可

onclick="test(123,event)"
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    *{
      color: white;
      font-size: 20px;
    }
    #outer{
      width: 300px;
      height: 300px;
      background-color: red;
    }
    #center{
      width: 200px;
      height: 200px;
      background-color: blue;
    }
    #inner{
      width: 100px;
      height: 100px;
      background-color: green;
    }
  </style>
</head>
<body>
  <div id="outer">outer
    <div id="center">center
      <!-- 第一种:匿名函数 ,整体性好-->
      <!-- <div id="inner" onclick="myFun(123,event)">inner</div> -->
      <!-- 第二种:有名函数 -->
      <div id="inner" onclick="myFun(123,event)">inner</div>
    </div>
  </div>
  <script>
    var inner = document.getElementById('inner');
    var center = document.getElementById('center');
    var outer = document.getElementById('outer');
/*     // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样
   //第一种:匿名函数
    inner.onclick = function (event) {
      console.log('我是inner点击的');
      //阻止事件冒泡
      event.stopPropagation();
    } */

    // 第二种:有名函数
    var myFun=function(a,event){
      console.log(a,event);
    }

    // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象
    center.onclick = function () {
      console.log('我是center点击的');
    }
    outer.onclick = function () {
      console.log('我是outer点击的');
    }
  </script>
</body>
</html>

效果: 点击inner之后只会输出inner,而后面父级的不会输出center、outer了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值