Web APIs 3:事件流、事件委托

news/2024/9/30 10:13:27 标签: 前端, javascript, html

Web APIs 3(事件流、事件委托)

1.事件流
  • 事件流:事件完整执行过程中的流动路径
  • 捕获阶段:从DOM根元素开始去执行对应的事件(从外到里)
DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)

eg : 分别给document、父级div、子机div都注册同一个事件监听,则从外到内执行

  • 冒泡阶段:当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发(当一个元素触发事件后,会依次向上调用所有父级元素的同类型事件)

  • 阻止冒泡

    • 问题:默认有冒泡模式的存在,容易导致事件影响父级元素
    • 需求:想把事件就限制在当前元素内,需要阻止事件冒泡
    • 前提:阻止事件冒泡要先拿到事件对象
    • 语法:阻止事件流,不仅对冒泡有用,对捕获也有用
    事件对象.stopPropagation()
    

    示例:点击son盒子时,事件流被阻止,只会弹出“我是儿子”

    html"><head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .father {
          width: 400px;
          height: 400px;
          background-color: aqua;
        }
    
        .son {
          width: 200px;
          height: 200px;
          background-color: blueviolet;
        }
      </style>
    </head>
    
    <body>
      <div class="father">
        <div class="son"></div>
      </div>
      <script>html" title=javascript>javascript">
        const fa = document.querySelector('.father')
        const son = document.querySelector('.son')
        document.addEventListener('click', function () {
          alert('我是爷爷')
        })
        fa.addEventListener('click', function () {
          alert('我是爸爸')
        })
        son.addEventListener('click', function (e) {
          alert('我是儿子')
          e.stopPropagation()
        })
      </script>
    </body>
    
  • 解绑事件

    元素.removeEventListener(‘事件类型’,事件处理函数)

    • 注意:匿名函数无法被解绑
    btn.removeEventListener('click',函数名)
    
2.事件委托
  • 优点:减少时事件监听注册的次数,提高程序性能

  • 原理:利用事件冒泡的特点,给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件

  • 实现:事件对象.target可以获得真正触发事件的元素

    html"><body>
      <ul>
        <li>第1个孩子</li>
        <li>第2个孩子</li>
        <li>第3个孩子</li>
        <li>第4个孩子</li>
        <li>第5个孩子</li>
        <p>我不需要变色</p>
      </ul>
      <script>html" title=javascript>javascript">
        const ul = document.querySelector('ul')
        ul.addEventListener('click', function (e) {
          console.log(e.target); //点击的对象
          //只要点li变色,p不要变色
          if (e.target.tagName === 'LI') {
            e.target.style.color = 'red'
          }
        })
      </script>
    </body>
    
  • 阻止默认行为的发生:e.preventDefault()

    eg:点击提交默认直接提交,但表单信息有误时不允许提交,就需要使用该阻止方式

    html"><body>
      <form action="http://www.baidu.com">
        <input type="submit" value="提交">
      </form>
      <script>html" title=javascript>javascript">
        const form = document.querySelector('form')
        form.addEventListener('click', function (e) {
          e.preventDefault()
        })
      </script>
    </body>
    
3.其他事件
  • 页面加载事件

    • 定义:加载外部资源(如图片、外联CSS、JavaScript)加载完毕时触发的事件
    • 使用场景:需要等页面资源全部处理完再做一些事情,eg:如果将script代码写到head中,直接找dom元素找不到
    • load事件:监听页面所有资源加载完毕:给window添加load事件(当然也可以给针对某个资源绑定load事件)
    html"><head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <script>html" title=javascript>javascript">
        //等待页面所有资源加载完毕就会执行回调函数
        window.addEventListener('load', function () {
          const btn = document.querySelector('button')
          btn.addEventListener('click', function () {
            alert("你好")
          })
        })
      </script>
    </head>
    
    <body>
      <button>点击</button>
    </body>
    
    • DOMContentLoaded事件:当HTML文档被完全加载和解析完后,无需等待样式表、图像等完全加载:给document添加DOMContenLoaded事件
  • 元素滚动事件

    • 滚动条滚动触发的事件
    • scroll事件:监听整个页面滚动(也可以监听某个元素滚动)
    <script>
        window.addEventListener('scroll', function () {
          console.log("滚动")
        })
      </script>
    
    • 获取滚动位置的属性:scrollLeft|scrollTop(可读写)
    <script>
        const div = document.querySelector('div')
        window.addEventListener('scroll', function () {
          //document.documentElement返回HTML元素
          const n = document.documentElement.scrollTop
          console.log(n)
          if (n >= 100) {
            div.style.display = 'block'
          } else {
            div.style.display = 'none'
          }
        })
      </script>
    
    • 滚动到指定坐标:元素.scrollTo(x,y)
  • 页面尺寸事件

    • 窗口尺寸发生改变时触发事件
    • resize
    <script>
        window.addEventListener('resize', function () {
          console.log(11);
        })
      </script>
    
    • 检测屏幕尺寸——获取元素宽高
      • clientWidth、clientHeight(不包含边框,margin,滚动条等,只读)
4.元素尺寸位置
  • 获取宽高:offsetWidth和offsetHeight(包含边框,只读)
  • 获取位置:offsetLeft和offsetTop(只读):元素距离父级元素左上距离

案例:实现滚动到秒杀模块位置后,顶部导航滑动出现,再返回到秒杀模块上方后,顶部导航隐藏

<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>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .content {
            overflow: hidden;
            width: 1000px;
            height: 3000px;
            background-color: pink;
            margin: 0 auto;
        }

        .backtop {
            display: none;
            width: 50px;
            left: 50%;
            margin: 0 0 0 505px;
            position: fixed;
            bottom: 60px;
            z-index: 100;
        }

        .backtop a {
            height: 50px;
            width: 50px;
            background: url(./images/bg2.png) 0 -600px no-repeat;
            opacity: 0.35;
            overflow: hidden;
            display: block;
            text-indent: -999em;
            cursor: pointer;
        }

        .header {
            position: fixed;
            top: -80px;
            left: 0;
            width: 100%;
            height: 80px;
            background-color: purple;
            text-align: center;
            color: #fff;
            line-height: 80px;
            font-size: 30px;
            transition: all .3s;
        }

        .sk {
            width: 300px;
            height: 300px;
            background-color: skyblue;
            margin-top: 500px;
        }
    </style>
</head>
<body>
    <div class="header">我是顶部导航栏</div>
    <div class="content">
        <div class="sk">秒杀模块</div>
    </div>
    <div class="backtop">
        <img src="../images/close2.png" alt="">
        <a href="html" title=javascript>javascript:;"></a>
    </div>
    <script>
        const sk = document.querySelector('.sk')
        const header = document.querySelector('.header')
        window.addEventListener('scroll', function () {
            const n = document.documentElement.scrollTop
           /* if (n >= sk.offsetTop) {
                header.style.top = 0
            } else {
                header.style.top = '-80px'
            } */
            header.style.top = n >= sk.offsetTop ? 0 : '-80px'
        })
    </script>
</body>

</html>
  • 总结:
属性作用说明
scrollLeft|scrollTop被卷去的头部和左侧配合页面滚动使用,可读写
clientWidth|clientHeight获取元素宽度和高度不包含border,margin,滚动条,用于获取元素大小,只读属性
offsetWidth|offsetHeight获得元素宽度和高度包含border、padding,滚动条等,只读
offsetLeft|offsetTop获取元素距离自己定位父级元素的左、上距离获取元素位置的时候使用,只读

http://www.niftyadmin.cn/n/5684879.html

相关文章

redis和mysql端口修改

因为之前有过被删库勒索的情况所以&#xff0c;今天记录一下怎么修改端口。 redis 要修改Redis的端口&#xff0c;您需要编辑Redis配置文件&#xff0c;通常名为redis.conf。 找到Redis配置文件&#xff1a; 在Linux系统上&#xff0c;该文件通常位于/etc/redis/redis.conf…

生产环境升级mysql流程及配置主从服务

之前写到过mysql升级8.4的文章, 因此不再介绍mysql的安装过程 避免服务器安装多个mysql引起冲突的安装方法_安装两个mysql会冲突吗-CSDN博客 生产环境升级mysql8.4.x流程 安装mysql 参考之前文章: 避免服务器安装多个mysql引起冲突的安装方法_安装两个mysql会冲突吗-CSDN博客…

阳光能源嵌入式面试及参考答案(2万字长文)

管道能够承载的最大传输数据量是多少? 在嵌入式系统中,管道能够承载的最大传输数据量取决于多个因素。 首先,管道的容量受到操作系统的限制。不同的操作系统对管道的大小有不同的规定。一般来说,管道的容量通常是有限的,并且在不同的操作系统版本和配置下可能会有所不同。…

在 C++ std::set 中如何利用不同类型的值进行搜索?

在 C 集合中如何利用不同类型的值进行搜索 一、背景二、初衷三、is_transparent四、总结 一、背景 C14 引入了一项引人注目的功能&#xff0c;为关联容器弥补了某些案例中长久以来的不足之处&#xff1a;即允许使用在语义上被视为键&#xff0c;但在技术上并非真正键的值对关联…

技术成神之路:设计模式(十八)适配器模式

介绍 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许接口不兼容的类可以协同工作&#xff0c;通过将一个类的接口转换成客户端所期望的另一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的类可以一起工作。 1.定义 适配…

mysql怎么修改一个字段中的所有部分数据

UPDATE videos SET VideoCode replace(VideoCode,flv,mp4); update 表名 set 字段名 replace&#xff08;字段名&#xff0c;‘修改前’&#xff0c;‘修改后’&#xff09;&#xff1b;

如何处理各行业的DDOS问题

分布式拒绝服务&#xff08;Distributed Denial of Service, DDoS&#xff09;攻击是网络安全领域最为常见且危害性极大的攻击方式之一。通过控制大量计算机、物联网终端或网络僵尸&#xff0c;攻击者能够向目标网站或服务器发送大量请求&#xff0c;从而耗尽其资源&#xff0c…

【解密 Kotlin 扩展函数】扩展属性与扩展函数类似(十九)

导读大纲 1.1.1 扩展属性的创建和使用 1.1.1 扩展属性的创建和使用 之前, 我们已经了解声明 Kotlin 属性的语法 Kotlin中的顶级属性–传送门就像扩展函数一样,我们也可以指定扩展属性就像之前所说&#xff0c;属性和函数的区别在于前者是特征&#xff0c;后者是行为 相比扩展函…