【Web APIs】事件高级

目录

1.事件对象

1.1获取事件对象

1.2事件对象常用属性

2.事件流

1.1事件流的两个阶段:冒泡和捕获

1.2阻止事件流动

1.3阻止默认行为

1.4两种注册事件的区别

3.事件委托


1.事件对象

1.1获取事件对象

**事件对象:**也是一个对象,这个对象里有事件触发时的相关信息

例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置的信息

获取事件对象:

  • 在事件绑定的回调函数的第一个参数就是事件对象
  • 一般命名为event,ev,e

语法: 元素.addEventListener('click', function(e) { }) e就是事件对象

1.2事件对象常用属性

常用属性

  • type:获取当前事件类型
  • clientX/clientY:获取光标相对于浏览器可见窗口左上角的位置
  • pageX/pageY:获取光标相对于浏览器窗口左上角的位置
  • offsetX/offsetY:获取光标相对于当前DOM元素左上角的位置
  • key:用户按下的键盘键的值(现在不再使用keyNode)

案例:图片跟随鼠标

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        img {
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>
<body>
    <img src="./pictures/tianshi.gif" alt="">

    <script>
        let img = document.querySelector('img')
        document.addEventListener('mousemove', function(e) {
            // 鼠标坐标赋值给图片
            // 减值是为了让鼠标在图片上面
            img.style.left = e.pageX - 50 + 'px'
            img.style.top = e.pageY - 40 + 'px'

        })
        
    </script>
</body>
</html>

2.事件流

1.1事件流的两个阶段:冒泡和捕获

事件流:事件完整执行过程中的流动路径

假设页面里有一个div,当触发事件时,会经历两个阶段:捕获阶段和冒泡阶段

①事件冒泡:

当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发(依次向上调用所有父级元素的同名事件),这一过程称为事件冒泡

📖Note:

  • 事件冒泡是默认存在的

②事件捕获:

从DOM的根元素开始去执行对应的事件(从外到里)

📖Note:

  • 事件捕获需要写对应的代码才能看到
  • DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制),第三个参数传入true代表是捕获阶段触发(不常用),传入false代表冒泡阶段触发,默认false
  • 若是用L0事件监听,则只有冒泡阶段,没有捕获阶段

捕获:父级到子级 冒泡:子级到父级

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>

        .grand {
            margin: 100px;
            width: 500px;
            height: 500px;
            background-color: red;
        }

        .father {
            width: 400px;
            height: 400px;
            background-color: pink;
        }
        .son {
            width: 200px;
            height: 200px;
            background-color: skyblue;
        }


    </style>
</head>
<body>

    <div class="grand">
        <div class="father">
            <div class="son"></div>
        </div>
    </div>

    <script>
        let grand = document.querySelector('.grand')
        let father = document.querySelector('.father')
        let son = document.querySelector('.son')

        grand.addEventListener('click', function(e) {
            alert('爷爷级元素的点击事件')
        })

        father.addEventListener('click', function() {
            alert('父级元素的点击事件')
        })

        son.addEventListener('click', function() {
            alert('子级元素的点击事件')
        })

        
    </script>
</body>
</html>

上面的案例中,当点击子级元素时,先触发子级元素的绑定的点击事件,再依次向上触发父级元素绑定的点击事件,依次类推,直到访问完所有的父级元素,这个过程即为事件冒泡

事件捕获的过程同理:只不过是从根元素向下访问所有的子级元素

1.2阻止事件流动

冒泡模式默认存在,可能会导致事件影响到父级元素;若想把事件限制在当前元素内,就要阻止事件流动

语法: 时间对象.stopPropagation()

📖Note:

  • 阻止事件流动需要拿到事件对象,因此回调函数的形参列表必须写e/event

上面的案例中:组织事件流动后,当点击子级元素时,只触发子级元素的点击事件,不会触发父级元素的点击事件

**📖Note:**鼠标经过事件

  • mouseover和mouseout会有冒泡效果
  • mouseenter和mouseleave没有冒泡效果(推荐)

1.3阻止默认行为

默认行为,比如链接点击不跳转,表单域的跳转

语法: e.preventDefault()

1.4两种注册事件的区别

两种注册事件的区别:

传统on注册(L0)

  • 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
  • 直接使用null覆盖偶就可以实现事件的解绑
  • 都是冒泡阶段执行的

事件监听注册(L2)

  • 语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)、
  • 后面注册的事件不会覆盖前面注册的事件(同一个事件)
  • 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
  • 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
  • 匿名函数无法被解绑

3.事件委托

利用事件流的特征解决一些开发需求

场景:多个子级元素进行同样的操作时,可以将这个操作委托给父级元素;比如所有的子级元素都要绑定点击事件,则可以给它们的父级添加点击事件,由于冒泡模式默认存在,所以当自身没有绑定点击事件时,会触发父级的点击事件

获取点击的对象,语法:e.target

获取点击的对象的名字,语法:e.target.tagName

相关推荐
裕波几秒前
AI 正在重写应用开发。Vue 与 Vite,给出新的答案。
javascript·vue.js
kyriewen1 小时前
折腾了半年 AI 编程工作流,最后发现效率瓶颈是桌上那块屏幕
前端·javascript·ai编程
张元清4 小时前
React useDebounce Hook:给状态和回调做防抖(2026)
javascript·react.js
Cobyte5 小时前
21.Vue Vapor 组件的实现原理
前端·javascript·vue.js
铁皮饭盒5 小时前
Rust版Bun1.4之前, 盘点Bun1.3新特性
前端·javascript·后端
晓得迷路了5 小时前
栗子前端技术周刊第 135 期 - Vite 8.1、Rspack 2.1、Babel 8.0...
前端·javascript·vite
To_OC14 小时前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC14 小时前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
天渺工作室15 小时前
实现一个adblock/adblock plus等浏览器广告拦截器检测插件
前端·javascript
kyriewen1 天前
2026 年了,还在用 Node.js?Bun 迁移实战:20 分钟搞定,附踩坑记录
前端·javascript·node.js