LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

[转帖]玩转js事件机制

freeflydom
2023年5月18日 8:41 本文热度 382

js事件机制



正文

首先,我们要知道js事件流的概念。

一、js事件流

js事件流一共分为三个阶段

  1. 从 window上  事件触发处 传播,遇到 注册的捕获事件 就会触发。

  2. 传播到事件触发处,触发注册的事件。

  3. 从 事件触发处  window上 传播,遇到 注册的冒泡事件 触发。

来张图让你更好的理解:

二、举个例子

我们要实现这个效果,定义三个容器,给三个容器都添加一个点击监听事件,点击相应的容器并输出相应的打印。我们需要观察的是点击相应的容器输出结果

image.png

1.第一种情况

addEventListener监听事件只有两个参数时

代码如下:

<!DOCTYPE html>

<html>

<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>

    #greenBox{

      width: 200px;

      height: 200px;

      background: #c2f5ca;

    }

    #pinkBox{

      width: 100px;

      height: 100px;

      background-color: #f7d0d0;

      color:#fff;  

      position: absolute;

    }

    #blackBox{

      width: 50px;

      height: 50px;

      background: #000;

    }

  </style>


 

</head>

<body>

  <div id="greenBox">

    <div id="pinkBox">

      <div id="blackBox"></div>

    </div>

  </div>

  

  <script> 

    let greenBox=document.getElementById('greenBox')

    let pinkBox=document.getElementById('pinkBox')

    let blackBox=document.getElementById('blackBox')


    greenBox.addEventListener('click',()=>{

      console.log('greenBox')

    })

    pinkBox.addEventListener('click',(event)=>{

      console.log('pinkBox') 

    })

    blackBox.addEventListener('click',(event)=>{

      console.log('blackBox')

    })

  </script>

</body>

</html>

当我们点击黑色容器时,得到的打印结果:

image.png

这是为什么呢?

答:因为addEventListener是存在第三个参数的,当没有第三个参数时,默认是遇到注册的冒泡事件触发。
1)当js事件流从window上事件触发处传播的过程中,并没有遇到注册的捕获事件,故不会触发;
2)当js事件流从事件触发处window上传播的过程中,首先遇到的是blackBox注册的的冒泡事件,之后是pinkBox,最后是greenBox

2.第二种情况

当addEventListener监听事件有三个参数时,第三个参数为truefalse。当第三个参数为false时,只在遇到注册的冒泡事件触发;为true时,只在遇到注册的捕获事件触发。

1)我们在greenBox的监听事件中添加第三个参数true,代码如下:

 

 <script> 

    greenBox.addEventListener('click',()=>{

      console.log('greenBox')

    },true)

    pinkBox.addEventListener('click',(event)=>{

      console.log('pinkBox') 

    })

    blackBox.addEventListener('click',(event)=>{

      console.log('blackBox')

    })

  </script>


当我们点击黑色容器时,得到的打印结果:

image.png

这是为什么呢?

答:因为greenBox的addEventListener存在的第三个参数为true,则说明greenBox只在遇到注册的捕获事件触发。
1)当js事件流从window上事件触发处传播的过程中,遇到greenBox注册的捕获事件,故触发greenBox
2)当js事件流从事件触发处window上传播的过程中,首先遇到的是blackBox注册的的冒泡事件,之后是pinkBox

2)我们在greenBox的监听事件中添加第三个参数false,在pinkBox的监听事件中添加第三个参数true,代码如下:

<script> 

    greenBox.addEventListener('click',()=>{

      console.log('greenBox')

    },flase)

    pinkBox.addEventListener('click',(event)=>{

      console.log('pinkBox') 

    },true)

    blackBox.addEventListener('click',(event)=>{

      console.log('blackBox')

    })

  </script>

当我们点击黑色容器时,得到的打印结果:

image.png

这个结果也是在意料之中的,首先pinkBox在遇到注册的的捕获事件触发,而blackBox默认在遇到注册的的冒泡事件触发,greenBox在遇到注册的的冒泡事件触发。

三、阻止默认事件

当我们想只触发其中的一个或多个事件,而其它事件不触发时,我们可以使用stopPropagation()stopImmediatePropagation()函数。

stopPropagation() : 终止默认事件传播到其他容器

stopImmediatePropagation() : 终止默认事件传播到其他容器上 和 自己这个容器的其他事件

四、事件代理

事件代理是js事件机制一个重要的应用

1.来个例子

我们要实现一个列表,其中有五项,点击任何一项输出相应的列表项文本。

我们大多数小白会这么写,采用循环进行遍历:

<!DOCTYPE html>

<html>


<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>

</head>

<style>

  li {

    width: 100px;

    background: #efe5ad;

    font-size: 20px;

    margin: 10px;

  }

</style>


<body>

  <ul id="ul">

    <li>1</li>

    <li>2</li>

    <li>3</li>

    <li>4</li>

    <li>5</li>

  </ul>


  <script>

     let li = document.getElementsByTagName("li");

     for (let i = 0; i < li.length; i++) {

       li[i].addEventListener("click", () => {

         console.log(li[i].innerHTML)

       })

     }

  </script>

</body>


</html>

但是这样做每次循环都需要创建一个监听事件,这就不优雅了,试着利用js事件流优化它一下吧!

<script>

    //事件代理 

    let ul = document.getElementById("ul");

    ul.addEventListener("click", (event) => {

      console.log(event.target.innerHTML);

    })

  </script>

我们只需要获取uldom结构,调用ul监听事件参数event中的taget中的innerHTML就可以得到值啦!

2.优点

  • 只需要把事件绑定到ul上,占用的内存更小

  • 可以动态给添加的元素绑定监听事件,不需要每添加一个元素就重新绑定一次。

最后

我们开头的问题想必大家都有答案了,是因为在菜品这个div中默认设置了阻止默认事件的函数stopPropagation(),当点击按钮时会触发这个按钮的冒泡事件。故点击按钮并不会跳转到这个菜品的详情页。


-------------------------------

https://juejin.cn/post/7232905822279204919



该文章在 2023/5/18 8:44:09 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved