JavaScript的事件监听

news2024/11/16 19:37:04

一、认识事件处理

1.认识事件

Web页面需要经常和用户之间进行交互,而交互的过程中我们可能想要捕捉这个交互的过程:

  • 比如用户点击了某个按钮用户在输入框里面输入了某个文本用户鼠标经过了某个位置
  • 浏览器需要搭建一条JavaScript代码和事件之间的桥梁
  • 当某个事件发生时,让JavaScript可以响应(执行某个函数),所以我们需要针对事件编写处理程序(handler);

如何进行事件监听呢?

  • 事件监听方式一:在script中直接监听(很少使用);
  • 事件监听方式二:DOM属性,通过元素的on来监听事件;
  • 事件监听方式三:通过EventTarget中的addEventListener来监听;
<body>
  <!-- 监听方式一 script--> 
  <button onclick="alert('hello world');">nihao1</button>
  <button>nihao2</button>
  <button>nihao3</button>
  <script>
    // 监听方式二 on
    var btn2El = document.body.children[1];
    btn2El.onclick = function () {
      alert("监听方式2");
    }

    // 监听方式三 addListenEvent
    var btn3El = document.body.children[2];
    btn3El.addEventListener("click", function () {
      alert("监听方式3");
    })

</script>

2.常见的事件列表

鼠标事件:

  • click —— 当鼠标点击一个元素时(触摸屏设备会在点击时生成)。
  • mouseover / mouseout —— 当鼠标指针移入/离开一个元素时。
  • mousedown / mouseup —— 当在元素上按下/释放鼠标按钮时。
  • mousemove —— 当鼠标移动时。

键盘事件:

  • keydown 和 keyup —— 当按下和松开一个按键时。

表单(form)元素事件:

  • submit —— 当访问者提交了一个<form> 时。
  • focus —— 当访问者聚焦于一个元素时,例如聚焦于一个<input>

Document 事件:

  • DOMContentLoaded —— 当 HTML 的加载和处理均完成,DOM 被完全构建完成时。

CSS 事件:

  • transitionend —— 当一个 CSS 动画完成时。

二、事件冒泡捕获

1.认识事件流

事实上对于事件有一个概念叫做事件流,为什么会产生事件流呢?

  • 我们可以想到一个问题:当我们在浏览器上对着一个元素点击时,你点击的不仅仅是这个元素本身
  • 这是因为我们的HTML元素是存在父子元素叠加层级的;
  • 比如一个span元素是放在div元素上的,div元素是放在body元素上的,body元素是放在html元素上的;
<div class="box">
    <span class="word">哈哈哈哈</span>
</div>
// 认识事件流
var boxEl = document.querySelector(".box");
var wordEl = document.querySelector(".word");
boxEl.addEventListener("click", function() {
    console.log("boxboxbox");
})
wordEl.addEventListener("click", function () {
    console.log("wordwordword");
})

2.事件冒泡和事件捕获

我们会发现默认情况下事件是从最内层的span向外依次传递的顺序,这个顺序我们称之为事件冒泡(Event Bubble);

事实上,还有另外一种监听事件流的方式就是从外层到内层(body -> span),这种称之为事件捕获(Event Capture);

为什么会产生两种不同的处理流呢?

  • 这是因为早期浏览器开发时,不管是IE还是Netscape公司都发现了这个问题;
  • 但是他们采用了完全相反的事件流来对事件进行了传递;
  • IE采用了事件冒泡的方式,Netscape采用了事件捕获的方式;

那么我们如何去监听事件捕获的过程呢?

在这里插入图片描述

3.事件捕获和冒泡的过程

如果我们都监听,那么会按照如下顺序来执行:

捕获阶段(Capturing phase):

  • 事件(从 Window)向下走近元素。

目标阶段(Target phase):

  • 事件到达目标元素。

冒泡阶段(Bubbling phase):

  • 事件从元素上开始冒泡。

事实上,我们可以通过event对象来获取当前的阶段:

  • eventPhase

开发中通常会使用事件冒泡,所以事件捕获了解即可。

在这里插入图片描述

// 默认情况下是事件冒泡
spanEl.addEventListener("click", function() {
    console.log("span元素发生了点击~冒泡")
})
divEl.addEventListener("click", function() {
    console.log("div元素发生了点击~冒泡")
})
bodyEl.addEventListener("click", function() {
    console.log("body元素发生了点击~冒泡")
})

// 设置希望监听事件捕获的过程
spanEl.addEventListener("click", function() {
    console.log("span元素发生了点击~捕获")
}, true)
divEl.addEventListener("click", function() {
    console.log("div元素发生了点击~捕获")
}, true)
bodyEl.addEventListener("click", function() {
    console.log("body元素发生了点击~捕获")
}, true)

三、事件对象event

1.事件对象

当一个事件发生时,就会有和这个事件相关的很多信息:

  • 比如事件的类型是什么,你点击的是哪一个元素点击的位置是哪里等等相关的信息;
  • 那么这些信息会被封装到一个Event对象中,这个对象由浏览器创建,称之为event对象
  • 该对象给我们提供了想要的一些属性,以及可以通过该对象进行某些操作;

如何获取这个event对象呢?

  • event对象会在传入的事件处理(event handler)函数回调时,被系统传入;
  • 我们可以在回调函数中拿到这个event对象;

这个对象中都有哪些常见的属性和操作呢?

2.event常见的属性和方法

常见的属性:

  • type:事件的类型;
  • target:当前事件发生的元素;
  • currentTarget:当前处理事件的元素;
  • eventPhase:事件所处的阶段;
  • offsetXoffsetY:事件发生在元素内的位置;
  • clientXclientY:事件发生在客户端内的位置;
  • pageXpageY:事件发生在客户端相对于document的位置;
  • screenXscreenY:事件发生相对于屏幕的位置;

常见的方法:

  • preventDefault:取消事件的默认行为;
  • stopPropagation:阻止事件的进一步传递(冒泡或者捕获都可以阻止);
// 认识事件流
var boxEl = document.querySelector(".box");
var wordEl = document.querySelector(".word");
// 事件冒泡
wordEl.addEventListener("click", function (event) {
    console.log("word冒泡", event.target, event.currentTarget);
    console.log(event.type);//click
    console.log(event.eventPhase);//2
})
wordEl.addEventListener("click", function (event) {
    console.log("word捕获", event.target, event.currentTarget);
    console.log(event.type);//click
    console.log(event.eventPhase);//2
}, true)
boxEl.addEventListener("click", function (event) {
    console.log("box捕获", event.target, event.currentTarget);
    console.log(event.type);//click
    console.log(event.eventPhase);//1
}, true)
document.body.addEventListener("click", function (event) {
    console.log("body捕获", event.target, event.currentTarget);
    console.log(event.type);//click
    console.log(event.eventPhase);//1
    // 停止传递
    // event.stopPropagation();
}, true)
var aEl = document.querySelector("a");
console.log(aEl);
console.log(aEl.href);
aEl.addEventListener("click", function (event) {
    console.log("a标签冒泡");
    // 阻止默认行为:比如a标签的跳转
    event.preventDefault();
})

3.事件处理中的this

在函数中,我们也可以通过this来获取当前的发生元素:

divEl.onclick = function(event) {
    console.log(this)
    console.log(event.currentTarget)
    console.log(divEl)
    console.log(this === divEl)
}

这是因为在浏览器内部,调用event handler是绑定到当前的target上的

四、EventTarget使用

1.EventTarget类

我们会发现,所有的节点、元素都继承自EventTarget

  • 事实上Window也继承自EventTarget;

那么这个EventTarget是什么呢?

  • EventTarget是一个DOM接口,主要用于添加删除派发Event事件;

EventTarget常见的方法:

  • addEventListener:注册某个事件类型以及事件处理函数;
  • removeEventListener:移除某个事件类型以及事件处理函数;
  • dispatchEvent:派发某个事件类型到EventTarget上;
var btnEl = document.querySelector("button")

// 1.将监听函数移除的过程
// var foo = function() {
//   console.log("监听到按钮的点击")
// }
// btnEl.addEventListener("click", foo)

// // 需求: 过5s钟后, 将这个事件监听移除掉
// setTimeout(function() {
//   btnEl.removeEventListener("click", foo)
// }, 5000)

// 这种做法是无法移除的
btnEl.addEventListener("click", function() {
    console.log("btn监听的处理函数~")
})

setTimeout(function() {
    btnEl.removeEventListener("click", function() {})
}, 5000)
// 派发事件
setTimeout(() => {
    // 3秒后触发点击事件
    btnEl.dispatchEvent(new Event("click"));
}, 3000);

五、事件委托模式

1.事件委托

事件冒泡在某种情况下可以帮助我们实现强大的事件处理模式 – 事件委托模式(也是一种设计模式)

那么这个模式是怎么样的呢?

  • 因为当子元素被点击时,父元素可以通过冒泡可以监听到子元素的点击
  • 并且可以通过event.target获取到当前监听的元素;

案例:一个ul中存放多个li,点击某一个li会变成红色

  • 方案一:监听每一个li的点击,并且做出相应;
  • 方案二:在ul中监听点击,并且通过event.target拿到对应的li进行处理;
    • 因为这种方案并不需要遍历后给每一个li上添加事件监听,所以它更加高效;
<!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>
    ul,li {
      list-style: none;
      margin: 0;
      padding: 0;
    }
    .item {
      display: inline-block;
      padding: 20px;
    }
    .active {
      background-color: yellow;
      color: blue;
    }
  </style>
</head>
<body>
  <ul>
    <li class="item">吃饭睡觉打豆豆</li>
    <li class="item">吃饭睡觉打豆豆</li>
    <li class="item">吃饭睡觉打豆豆</li>
    <li class="item">吃饭睡觉打豆豆</li>
    <li class="item">吃饭睡觉打豆豆</li>
  </ul>
  <script>
    var ulEl = document.querySelector("ul");
    ulEl.addEventListener("click", function (event) {
      // 委托模式
      // 获取触发事件的元素
      event.target.classList.toggle("active");
    })
  </script>
</body>
</html>

2.事件委托的标记

某些事件委托可能需要对具体的子组件进行区分,这个时候我们可以使用data-*对其进行标记:

比如多个按钮的点击,区分点击了哪一个按钮:

<!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>
</head>
<body>
  
  <div class="box">
    <button data-action="search">搜索~</button>
    <button data-action="new">新建~</button>
    <button data-action="remove">移除~</button>
    <button>1111</button>
  </div>

  <script>

    var boxEl = document.querySelector(".box")
    boxEl.onclick = function(event) {
      var btnEl = event.target
      var action = btnEl.dataset.action
      switch (action) {
        case "remove":
          console.log("点击了移除按钮")
          break
        case "new":
          console.log("点击了新建按钮")
          break
        case "search":
          console.log("点击了搜索按钮")
          break
        default:
          console.log("点击了其他")
      }
    }
  </script>

</body>
</html>

六、常见的事件

1.常见的鼠标事件

接下来我们来看一下常见的鼠标事件(不仅仅是鼠标设备,也包括模拟鼠标的设备,比如手机、平板电脑)

常见的鼠标事件:

在这里插入图片描述

1.1 mouseover和mouseenter的区别

mouseenter和mouseleave

  • 不支持冒泡
  • 进入子元素依然属于在该元素内,没有任何反应

mouseover和mouseout

  • 支持冒泡
  • 进入元素的子元素时
    • 先调用父元素的mouseout
    • 再调用子元素的mouseover
    • 因为支持冒泡,所以会将mouseover传递到父元素中;
var boxEl = document.querySelector(".box");
var containerEl = document.querySelector(".container");
// mouseenter mouseleave
// containerEl.addEventListener("mouseenter", function (event) {
//   console.log("鼠标进来拉")
// })
// containerEl.addEventListener("mouseleave", function (event) {
//   console.log("鼠标离开拉")
// })
// mouseover mouseout
containerEl.addEventListener("mouseover", function (event) {
    console.log("鼠标进来拉")
})
containerEl.addEventListener("mouseout", function (event) {
    console.log("鼠标离开拉")
})

2.常见的键盘事件

常见的键盘事件:
在这里插入图片描述

事件的执行顺序是 onkeydown、onkeypress、onkeyup

  • down事件先发生;
  • press发生在文本被输入;
  • up发生在文本输入完成;

我们可以通过key和code来区分按下的键:

  • code:“按键代码”(“KeyA”,“ArrowLeft” 等),特定于键盘上按键的物理位置。
  • key:字符(“A”,“a” 等),对于非字符(non-character)的按键,通常具有与 code 相同的值。
var inputEl = document.querySelector("input")
var btnEl = document.querySelector("button")

// inputEl.onkeydown = function() {
//   console.log("onkeydown")
// }
// inputEl.onkeypress = function() {
//   console.log("onkeypress")
// }
// inputEl.onkeyup = function(event) {
//   console.log(event.key, event.code)
// }

// 1.搜索功能
btnEl.onclick = function() {
    console.log("进行搜索功能", inputEl.value)
}

inputEl.onkeyup = function(event) {
    if (event.code === "Enter") {
        console.log("进行搜索功能", inputEl.value)
    }
}

// 2.按下s的时候, 搜索自动获取焦点
document.onkeyup = function(event) {
    if (event.code === "KeyS") {
        inputEl.focus()
    }
}

3.常见的表单事件

针对表单也有常见的事件:

在这里插入图片描述

var inputEl = document.querySelector("input")

// 1.获取焦点和失去焦点
// inputEl.onfocus = function() {
//   console.log("input获取到了焦点")
// }
// inputEl.onblur = function() {
//   console.log("input失去到了焦点")
// }

// 2.内容发生改变/输入内容
// 输入的过程: input
// 内容确定发生改变(离开): change
// inputEl.oninput = function() {
//   console.log("input事件正在输入内容", inputEl.value)
// }
// inputEl.onchange = function() {
//   console.log("change事件内容发生改变", inputEl.value)
// }

// 3.监听重置和提交
var formEl = document.querySelector("form")
formEl.onreset = function(event) {
    console.log("发生了重置事件")
    event.preventDefault()
}

formEl.onsubmit = function(event) {
    console.log("发生了提交事件")
    // axios库提交
    event.preventDefault()
}

4.文档加载事件

DOMContentLoaded:浏览器已完全加载 HTML,并构建了 DOM 树,但像<img> 和样式表之类的外部资源可能尚未加载 完成。

load:浏览器不仅加载完成了 HTML,还加载完成了所有外部资源:图片,样式等。

// 注册事件监听
window.addEventListener("DOMContentLoaded", function() {
    // 1.这里可以操作box, box已经加载完毕
    // var boxEl = document.querySelector(".box")
    // boxEl.style.backgroundColor = "orange"
    // console.log("HTML内容加载完毕")

    // 2.获取img对应的图片的宽度和高度
    var imgEl = document.querySelector("img")
    console.log("图片的宽度和高度:", imgEl.offsetWidth, imgEl.offsetHeight)
})

window.onload = function() {
    console.log("文档中所有资源都加载完毕")
    // var imgEl = document.querySelector("img")
    // console.log("图片的宽度和高度:", imgEl.offsetWidth, imgEl.offsetHeight)
}

window.onresize = function() {
    console.log("创建大小发生改变时")
}

事件类型:https://developer.mozilla.org/zh-CN/docs/Web/Events

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1012355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark on YARN 部署搭建详细图文教程

目录 一、引言 二、SparkOnYarn 本质 2.1 Spark On Yarn 的本质? 2.2 Spark On Yarn 需要啥? 三、配置 spark on yarn 环境 3.1 spark-env.sh 3.2 连接到 YARN 中 3.2.1 bin/pyspark 3.2.2 bin/spark-shell 3.2.3 bin/spark-submit (PI) 四、部署模式 DeployMod…

首发悬赏算命测算源码

可以用二维码收款 可以直接拿来运营吸金&#xff01; 用户可以通过发布悬赏赏金算命&#xff0c;也可以通过升级发布测算任务来吸金 安装教程&#xff1a; 测试环境&#xff1a;php5.6apache2.4mysq5.6 安装&#xff1a; 1.源码解压到根目录 修改 \Application\Common\Co…

学习Kotlin看哪些书?【赠书活动|第八期《深入实践Kotlin元编程》】

文章目录 图书简介01 《深入实践Kotlin元编程》02 《Spring Boot学习指南》03 《Kotlin编程实战》 抽奖方式 与Java一样&#xff0c;Kotlin也是用于Android应用程序开发的编程语言&#xff0c;是Android官方支持的第二种编程语言。 2016年Kotlin正式发布&#xff0c;在Android“…

【Flowable】任务监听器(五)

前言 之前有需要使用到Flowable&#xff0c;鉴于网上的资料不是很多也不是很全也是捣鼓了半天&#xff0c;因此争取能在这里简单分享一下经验&#xff0c;帮助有需要的朋友&#xff0c;也非常欢迎大家指出不足的地方。 一、监听器 在Flowable中&#xff0c;我们可以使用监听…

怎样下载和安装HBuilder软件?【附HBuilder快捷键】

HBuilder是一款深度集成Eelipse的IDE编辑器&#xff0c;但其主要集中在Web前端的开发&#xff0c;不能进行Java等后台开发。HBuilder提供了对JavaScrijpt、jQuery、HTML5、MUI等语法的提示功能&#xff0c;同时包含很多快捷键&#xff0c;让前端开发更加便捷。 访问HBuilder官…

全量数据采集:不同网站的方法与挑战

简介 在当今数字化时代中&#xff0c;有数据就能方便我们做出很多决策。数据的获取与分析已经成为学术研究、商业分析、战略决策以及个人好奇心的关键驱动力。本文将分享不同网站的全量数据采集方法&#xff0c;以及在这一过程中可能会遇到的挑战。 部分全量采集方法 1. 撞店…

1500*B. The Walkway(贪心规律)

解析&#xff1a; 把每个区间段分成左闭右开区间&#xff0c;我们可以观察到&#xff0c;每个区间的饼干数量为 ( r - l ) / d 上取整。 所以先计算不删除某个点的饼干总和init&#xff0c;然后遍历所有点&#xff0c;将这个点删除。所以删除某个点后剩余数量为&#xff1a; 找…

WOODWARD 5466-258 输入快速实施高效的闭环控制

WOODWARD 5466-258 输入快速实施高效的闭环控制 Malvern Instruments 增强了 Link II 软件包&#xff0c;可将多个分析仪集成到一个自动化控制平台中。最新的开发将 Malvern Link II 的优势扩展到该公司的 Mastersizer 和 Zetasizer 分析仪系列&#xff0c;简化了它们在过…

二蛋赠书二期:《Python机器学习项目实战》

文章目录 前言活动规则参与方式本期赠书《Python机器学习项目实战》作者介绍内容简介读者对象获奖名单 结语 前言 大家好&#xff01;我是二蛋&#xff0c;一个热爱技术、乐于分享的工程师。在过去的几年里&#xff0c;我一直通过各种渠道与大家分享技术知识和经验。我深知&am…

EMQX Enterprise 5.2 发布:Flow 设计器,Amazon Kinesis,Azure Event Hubs

EMQX Enterprise 5.2.0 版本现已正式发布&#xff01; 新版本带来了一系列重磅更新&#xff0c;最令人瞩目的是可拖拽的可视化 Flow 设计器&#xff0c;它可以帮助企业快速创建、测试和部署数据集成。同时&#xff0c;我们新增了对 Amazon Kinesis 和 Azure Event Hubs 的支持…

Python pip更换清华源镜像

Python pip更换清华源镜像 命令安装配置安装其它镜像 在安装Python库时使用清华源镜像是为了改善库的下载速度和稳定性地址&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 命令安装 安装命令&#xff1a; pip install 包名 -i https://pypi.tuna.tsinghua.edu.cn/simp…

Ubuntu使用System.Drawing.dll报错DllNotFoundException: libgdiplus.so.0

在Windows上开发的程序使用了System.Drawing.dll&#xff0c;放到Ubuntu上报错 解决方法&#xff1a;在Ubuntu上安装libgdiplus即可。 命令&#xff1a;sudo apt install libgdiplus 成功&#xff01;

huggingface.co 下载模型文件,死活找不到文件,也没报其他错误。原来是多了个%号

这样写&#xff0c;就没问题&#xff1a; snapshot_download(local_dir/content/drive/MyDrive/chatRWKV/models/,repo_id"BlinkDL/rwkv-4-raven", allow_patterns"RWKV-4-Raven-3B-v12-Eng49%-Chn49%-Jpn1%-Other1%-20230527-ctx4096.pth") 但是这个文件…

高电压+大电流 IGBT静态参数测试解决方案

近年来IGBT成为电力电子领域中尤为瞩目的电力电子器件,并得到越来越广泛的应用,那么IGBT的测试就变的尤为重要了。lGBT的测试包括静态参数测试、动态参数测试、功率循环、HTRB可靠性测试等,这些测试中最基本的测试就是静态参数测试。 IGBT静态参数主要包含:栅极-发射极阈值电压…

S7-1200PLC硬件中断编程应用(VN积分法计算实时卷径)

VN积分法计算实时卷径的算法原理请参考下面文章链接: VN积分法卷径计算FB(SCL代码)_RXXW_Dor的博客-CSDN博客卷径计算的其他方法请参看专栏的相关文章,链接如下:卷径计算(V/N法)_RXXW_Dor的博客-CSDN博客。https://rxxw-control.blog.csdn.net/article/details/131612206PL…

前端JavaScript深拷贝与浅拷贝

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 引言 1. 深拷贝的实现 1.1 基本类型和特殊类型的处理 1.2 处理循环引用 1.3 性能优化 1.4 完整的深拷贝实现示…

MES系统成为工业4.0首选,制造业真正数字化车间你看过吗?

在日益激烈的市场竞争中&#xff0c;MES管理系统已经成为企业提升生产效率、降低成本、提高竞争力的关键。通过MES管理系统实现数据集成和分析&#xff0c;能够对产品制造过程的各个环节进行可视化控制&#xff0c;从设计、制造、质量、物流等环节全面掌控信息&#xff0c;实现…

螺旋折线(找规律 + 准确取点优化分析 + 普通思路)【包含详细的思考过程】

螺旋折线 文章目录 螺旋折线前言题目描述题目分析优化思路知识点补充【曼哈顿距离】代码未优化思路【笨方法】 前言 在写完题目查看题解的时候&#xff0c;被acwing大佬的思路所震撼&#xff0c;所以按照自己的理解将 大佬的思路复刻一遍展现给大家&#xff0c;同时丰富了内容…

彩虹医疗器械彩超、内窥镜维修技能学习

近几年随着医疗行业的快速发展&#xff0c;医疗器械的需求量不断增加&#xff0c;同时对医疗器械的维修和保养需求也在不断增长随着医疗技术的不断进步&#xff0c;新型、复杂的医疗器械不断涌现&#xff0c;这对维修技术提出了更高的要求。加强技术研发是必经之路&#xff0c;…

Element Plus中Cascader 级联选择器(选择任意一级选项 - 更改下拉框选中方式)

组件原始选中&#xff1a;选择文字前面的单选按钮 现在更改为&#xff1a;隐藏单选按钮&#xff0c;点击文字进行选中 ① 给弹出内容的自定义类名(popper-class)&#xff1a; <el-cascader v-model"areaValue":options"areaOptions" :props"areaP…