事件

事件

_

一,事件监听

1.1 事件监听概述

  • 什么是事件?

    事件是在编程时系统内发生的动作或者发生的事情
    比如用户在网页上单击一个按钮

  • 什么是事件监听?
    就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 绑定事件或者注册事件
    比如鼠标经过显示下拉菜单,比如点击可以播放轮播图等等

  • 语法

    元素对象.addEventListener('事件类型',要执行的函数)
    
  • 事件监听三要素

    • 事件源:哪个dom元素被事件触发了,要获取dom元素
    • 事件类型:用什么方式触发,比如鼠标单击click,鼠标经过mouseover等
    • 事件调用的函数:要做什么事情
  • 举例

    <button>
        按钮
    </button>
    <script>
    	const btn = document.querySelector('.btn')
        //修改元素样式
        btn.addEventListener('click',function(){
            alert('点击')
        })
    </script>
    

1.2 事件监听的版本

  • DOM L0版本
    事件源.on事件=function(){}
  • DOM L2版本
    事件源.addEventListener(事件,事件处理函数)
  • 区别:
    on方式会被覆盖**,addEventListener方式可绑定多次**,拥有事件更多特性,推荐使用

1.3 事件类型

2953321-20240913101442957-1621597455.png

1.4 事件对象

  • 事件对象是什么?
    • 也是个对象,这个对象里有事件触发时的相关信息
    • 例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
  • 使用场景
    • 可以判断用户按下哪个键,比如按下回车键可以发布新闻
    • 可以判断鼠标点击了哪个元素,从而做相应的操作

1.4.1 获取事件对象

  • 语法:如何获取

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

    元素.addEventListener('click',function(e){
        //参数e就是事件对象
    })
    

1.4.2 事件对象常用属性

  • 部分常用属性

    • type
      • 获取当前的事件类型
    • clicentX/clientY
      • 获取光标相对于浏览器可见窗口左上角的位置
    • offsetX/offsetY
      • 获取光标相当于当前dom元素左上角的位置
    • key
      • 用户按下的键盘的值
      • 现状不提倡使用keyCode
  • 用法举例

    <button>
        按钮
    </button>
    <script>
    	const btn = document.querySelector('.btn')
        //修改元素样式
        btn.addEventListener('click',function(event){
            //获取用户按下的键盘值
            console.log(event.key)
            //获取当前事件类型
            console.log(event.type)
        })
    </script>
    

1.5 环境对象

环境对象:指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境。

作用:

  • 函数调用方式不同,this 指代的对象也不同

  • 谁调用,this 就是谁

    • 直接调用函数,就是相当于windows.函数,此时this指向的是window
    • 如果是按钮调用的函数,this指向的就是这个按钮对象
  • 举例

    function(){
        console.log(this)//指向的是window
    }
    const btn=document.querySelector('button')
    btn.addEventListener('click',function(){
        console.log(this)//返回的是btn对象
    })
    

二,事件流

2.1 事件流与两个阶段说明

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

2953321-20240913101442854-2133562303.png

说明:假设页面里有个 div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段

简单来说:捕获阶段是 从父到子, 冒泡阶段是从子到父

实际工作都是使用事件冒泡为主

2.2 事件捕获

事件捕获概念:

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

  • 代码:

    DOM元素.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
    
    • addEventListener第三个参数传入true代表的是捕获阶段触发(很少使用)
    • 如果传入false代表冒泡阶段触发,默认是false
  • 代码举例

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="./css/bootstrap.min.css" />
        <title>Document</title>
        <style>
          .father {
            width: 100px;
            height: 100px;
            background-color: red;
          }
          .son {
            width: 50px;
            height: 50px;
            background-color: blue;
          }
        </style>
      </head>
      <body>
        <div class="father">
          <div class="son"></div>
        </div>
    
        <script>
          const father = document.querySelector(".father");
          const son = document.querySelector(".son");
          document.addEventListener(
            "click",
            function (e) {
              alert("doc clicked");
            },
            true
          );
          father.addEventListener(
            "click",
            function (e) {
              alert("father clicked");
            },
            true
          );
          son.addEventListener(
            "click",
            function (e) {
              alert("son clicked");
            },
            true
          );
        </script>
      </body>
    </html>
    

2.3 事件冒泡

事件冒泡:当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡

简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的 同名事件

事件冒泡是默认存在的

L2 事件监听第三个参数是 false,或者默认都是冒泡

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/bootstrap.min.css" />
    <title>Document</title>
    <style>
      .father {
        width: 100px;
        height: 100px;
        background-color: red;
      }
      .son {
        width: 50px;
        height: 50px;
        background-color: blue;
      }
    </style>
  </head>
  <body>
    <div class="father">
      <div class="son"></div>
    </div>

    <script>
      const father = document.querySelector(".father");
      const son = document.querySelector(".son");
      document.addEventListener("click", function (e) {
        alert("doc clicked");
      });
      father.addEventListener("click", function (e) {
        alert("father clicked");
      });
      son.addEventListener("click", function (e) {
        alert("son clicked");
      });
    </script>
  </body>
</html>

2.4 阻止冒泡

  • 问题:因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素

  • 需求:若想把事件就限制在当前元素内,就需要阻止事件冒泡

  • 前提:阻止事件冒泡需要拿到事件对象

  • 语法:

    事件对象.stopPropagation()
    
  • 举例

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="./css/bootstrap.min.css" />
        <title>Document</title>
        <style>
          .father {
            width: 100px;
            height: 100px;
            background-color: red;
          }
          .son {
            width: 50px;
            height: 50px;
            background-color: blue;
          }
        </style>
      </head>
      <body>
        <div class="father">
          <div class="son"></div>
        </div>
    
        <script>
          const father = document.querySelector(".father");
          const son = document.querySelector(".son");
          document.addEventListener("click", function (e) {
            alert("doc clicked");
          });
          father.addEventListener("click", function (e) {
            alert("father clicked");
          });
          son.addEventListener("click", function (e) {
            alert("son clicked");
            //阻止流动
            e.stopPropagation();
          });
        </script>
      </body>
    </html>
    
  • 注意:此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效

2.5 解绑事件

  • on 事件方式,直接使用 null 覆盖偶就可以实现事件的解绑

    btn.onclick = function(){
        alert('点击')
    }
    //解绑事件
    btn.onclick=null
    
  • addEventListener 方式,必须使用,removeEventListener(事件类型,事件处理函数,[获取捕获或者冒泡阶段])

    function fn(){
        alert('点击')
    }
    //绑定事件
    btn.addEventListener('click',fn)
    //解绑事件
    btn.removeEventListener('click',fn)
    
    • 注意:匿名函数无法解绑

2.6 鼠标经过事件的区别

鼠标经过事件:

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

2.7 两种注册事件的区别

  • 传统on注册(L0)
    • 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
    • 直接使用null覆盖偶就可以实现事件的解绑
    • 都是冒泡阶段执行的
  • 事件监听注册(L2)
    • 语法: addEventListener(事件类型,事件处理函数,是否使用捕获)
    • 后面注册的事件不会覆盖前面注册的事件(同一个事件)
    • 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
    • 必须使用removeEventListener(事件类型,事件处理函数,获取捕获或者冒泡阶段)
    • 匿名函数无法被解绑

三,事件委托

事件委托是利用事件流的特征解决一些开发需求的知识技巧

  • 优点:减少注册次数,可以提高程序性能
  • 原理:事件委托其实是利用事件冒泡的特点。
    • 给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件。
  • 实现:事件对象.target.tagName可以获得真正触发事件的元素

代码举例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/bootstrap.min.css" />
    <title>Document</title>
  </head>
  <body>
    <ul>
      <li>第1个li</li>
      <li>第2个li</li>
      <li>第3个li</li>
      <li>第4个li</li>
      <li>第5个li</li>
      <p>第6个p</p>
    </ul>
    <script>
      const ul = document.querySelector("ul");
      ul.addEventListener("click", function (e) {
        if (e.target.tagName === "LI") {
          //只有li标签才会触发事件
          e.target.style.color = "red";
        }
      });
    </script>
  </body>
</html>

四,阻止标签默认行为

我们某些情况下需要阻止默认行为的发生,比如 阻止 链接的跳转,表单域跳转

  • 语法:

    事件对象.preventDefault();
    
  • 代码举例

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="./css/bootstrap.min.css" />
        <title>Document</title>
      </head>
      <body>
        <form action="https://www.baidu.com">
          <input type="submit" value="提交" />
        </form>
        <script>
          const form = document.querySelector("form");
          form.addEventListener("click", function (event) {
            //阻止表单默认提交行为
            event.preventDefault();
            alert("提交成功");
          });
        </script>
      </body>
    </html>
    

五,其他事件

5.1 页面加载事件

  • 加载外部资源 (如图片、外联 CSS 和 JavaScript 等) 加载完毕时触发的事件。

  • 为什么要学?

    • 有些时候需要等页面资源全部处理完了做一些事情
    • 老代码喜欢把 script 写在 head 中,这时候直接找 dom 元素找不到
  • 事件名:load

  • 监听页面所有资源加载完毕:

    • 给window添加load事件(window>document)
  • 代码举例

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="./css/bootstrap.min.css" />
        <title>Document</title>
        <script>
          //等待页面所有资源加载完毕,就回去指向回调函数
          window.addEventListener("load", function () {
            //获取元素
            var btn = document.querySelector("button");
            //绑定点击事件
            btn.addEventListener("click", function () {
              alert("按钮被点击了");
            });
          });
            img.addEventListener('load',function(){
               //等待图片加载完毕再执行里面的代码 
            });
        </script>
      </head>
      <body>
        <button>按钮</button>
      </body>
    </html>
    
  • 注:不光可以监听整个页面资源加载完毕,也可以针对某个资源绑定 load 事件


当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像等完全加载

  • 事件名:DOMContentLoaded

  • 监听页面 DOM 加载完毕

    • 给document添加DOMContentLoaded事件
  • 代码举例

    document.addEventListener('DOMContentLoaded',function(){
        //执行内容
    })
    

5.2 元素滚动事件

滚动条在滚动的时候持续触发的事件
作用:

  • 很多网页需要检测用户把页面滚动到某个区域后做一些处理,比如固定导航栏,比如返回顶部

  • 事件名:scroll

  • 监听整个页面滚动:

    //页面滚动事件
    window.addEventListener('scroll',function(){
        //执行的操作
    })
    
    • 给window或者document添加scroll事件

页面滚动事件 -》获取位置

  • scrollLeftscrollTop属性

    • scrollTop:页面往下滚动,元素超出的部分就是scrollTop
    • scrollLeft:页面往左边滚动,元素超出的部分就是scrollLeft
    • 单位是px

2953321-20240913103700539-96118959.png

  • 代码举例:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="./css/bootstrap.min.css" />
        <title>Document</title>
      </head>
      <style>
        div {
          margin: 400px auto;
          width: 100px;
          height: 200px;
          overflow: scroll;
          border: 1px solid black;
        }
      </style>
      <body>
        <div>
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
          我里面有很多内容11111111111111111111111111
        </div>
        <script>
          const div = document.querySelector("div");
          div.addEventListener("scroll", function () {
            console.log("scrollTop:" + div.scrollTop);
            console.log("scrollLeft:" + div.scrollLeft);
          });
        </script>
      </body>
    </html>
    
  • 获取页面滚动多少 px,被卷去多少 px

    document.documentElement.scrollTop//获取的是htm标签
    
  • 这俩个值是可读写

    我们可以给页面赋值,让页面打开显示在指定位置

    document.documentElement.scrollTop=800//让页面向下拉800px
    

5.3 页面尺寸事件

  • 会在窗口尺寸改变的时候触发事件:

    • resize
    window.addEventListener('resize',function(){
        //执行的code
    })
    
  • 检测屏幕官渡

    window.addEventListener('resize',function(){
        let width=document.documentElement.clientWidth
        console.log(width)
    })
    

页面尺寸事件 -》获取元素宽高

  • 获取元素的可见部分宽高,不包含 border,margin,滚动条

  • clientWidthclientHeight

2953321-20240913110726706-255217951.png

  • 代码举例

        <script>
          const div = document.querySelector("div");
          div.addEventListener("scroll", function () {
            div.clientHeight; // 内容的高度
            div.scrollHeight; // 内容的总高度
          });
        </script>
    

六,元素尺寸与位置

  • 使用场景

    • 前面案例滚动多少距离,都是我们自己算的,最好是页面滚动到某个元素,就可以做某些事。
    • 简单说,就是通过js的方式,得到元素在页面中的位置
    • 这样我们可以做,页面滚动到这个位置,就可以做某些操作,省去计算了
  • 获取宽高

    • 获取元素自身的宽高,包括元素自身设置的宽高,padding,border
    • offsetWidthoffsetHeight
    • 获取出来的是数值,方便计算
    • 注意:获取的是可视宽高,如果盒子是隐藏的,获取的结果是0
  • 获取位置

    • 获取元素距离自己定位父级元素的左、上距离
    • offsetLeftoffsetTop 注意是只读属性
  • 代码举例:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link rel="stylesheet" href="./css/bootstrap.min.css" />
        <title>Document</title>
      </head>
      <style>
        div {
          width: 200px;
          height: 200px;
          background-color: pink;
          margin: 100px;
        }
        p {
          width: 100px;
          height: 100px;
          background-color: purple;
          margin: 50px;
        }
      </style>
      <body>
        <div>
          <p></p>
        </div>
        <script>
          const div = document.querySelector("div");
          const p = document.querySelector("p");
          console.log(div.offsetLeft);
          console.log(p.offsetTop);
          console.log(div.offsetWidth);
          console.log(div.offsetHeight);
        </script>
      </body>
    </html>
    

  • 元素尺寸于位置 -》尺寸

    • 获取位置:元素对象.getBoundingClientRect()

    方法返回元素的大小以及相对于视口的位置

2953321-20240913113903307-308406451.png

七,M端事件

移动端也有自己独特的地方。比如触屏事件 touch(也称触摸事件),Android 和 I0S 都有。

  • 触屏事件 touch(也称触摸事件),Android 和 IOS 都有。

  • touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。触屏事件可响应用户手指 (或触控笔),对屏幕或者触控板操作。

  • 常见的触屏事件如下:

    触屏touch事件说明
    touchstart手指触摸到一个 DOM 元素时触发
    touchmove手指在一个 DOM 元素上滑动时触发
    touchend手指从一个 DOM 元素上移开时触发
操作dom 2026-06-09
日期对象 2026-06-09

© 2026 苏叶的belog