JavaScript 系列之:事件_document.addeventlistener
传播机制 - 事件流
在 DOM 中触发事件(如点击或鼠标移动)时,事件会经过一个或多个元素,形成所谓的“事件流”。DOM 事件流包含三个阶段:捕获阶段、目标阶段和冒泡阶段。
-
捕获阶段:
-
事件从 document 开始,沿着 DOM 树向下传播,直到触发事件的目标元素。
-
只有为捕获阶段注册的事件监听器会被触发。
-
-
目标阶段:
- 事件到达目标元素时,目标元素上的事件监听器会被触发。
-
冒泡阶段:
-
事件从目标元素开始,向上沿着 DOM 树传播,直到 document。
-
只有为冒泡阶段注册的事件监听器会被触发。
-
注意事项:
-
使用 addEventListener 注册事件时,第三个参数决定监听器是在捕获阶段还是冒泡阶段触发
-
默认情况下(第三个参数未设置或为 false),事件监听器在冒泡阶段触发。
-
如果指定第三个参数为 true,则在捕获阶段触发。
-
-
一种类型的事件不会触发不同类型的事件处理器。例如,click 事件不会触发 keydown 事件的处理器。
事件委托
在实际开发中,捕获阶段的应用相对较少,而冒泡阶段的应用则更为广泛。
开发者常利用冒泡阶段来监听多个元素的共同事件,从而减少代码的重复性。
一个典型的应用是事件委托,即将事件监听器绑定到父元素上,从而实现对动态添加子元素的事件监听。
这不仅减少了代码量,还能提高页面性能,降低内存消耗。
事件对象 - event
当事件被触发时,浏览器会创建一个事件对象,并将其作为参数传递给事件处理函数。
这个事件对象包含了与事件相关的所有信息:如事件的类型、触发事件的目标元素、鼠标的位置等。
通过事件对象,我们可以获取这些信息,并在事件处理函数中使用它们。
event 常用属性和方法:
target 和 currentTarget 的区别:
-
target:
-
target 是指实际触发事件的元素。即使事件通过事件冒泡(或捕获)传播,target 始终是事件最初发生的元素。
-
比如,如果你点击了一个按钮,而这个按钮被包含在一个 div 元素中,target 就是被点击的按钮,而不是包含它的 div。
-
-
currentTarget:
-
currentTarget 指的是当前正在处理事件的元素,通常是事件处理器绑定的元素。
-
如果你给父元素绑定了事件监听器,currentTarget 就是绑定事件的父元素,而不是实际触发事件的子元素。
-
事件监听器 - addEventListener
事件监听器 是一个函数,当指定事件发生在指定元素上时,该函数会被调用。可以通过 addEventListener() 方法为元素添加事件监听器。
语法:
addEventListener(type, listener, useCapture);
-
type:事件类型
-
listener:回调函数
-
useCapture:一个布尔值,定义事件是在冒泡阶段(默认)还是捕获阶段(true)触发
const element = document.getElementById(\'test\'); element.addEventListener(\'click\', function(event) { console.log(event) }); child.addEventListener(\'click\', function(event) { console.log(\'target:\', event.target); // 会输出触发事件的元素 console.log(\'currentTarget:\', event.currentTarget); // 会输出绑定事件监听器的元素 });
鼠标事件
mouseenter 和 mouseover 区别:
-
mouseenter “进入即触发,不冒泡”
-
仅在鼠标首次进入元素时触发,不考虑鼠标在元素内的移动或进入子元素的情况。
-
不支持事件冒泡,即当鼠标从子元素移动到父元素时,不会触发父元素的 mouseenter 事件。
-
-
mouseover “进入和移动都触发,且冒泡”
-
在鼠标进入元素时触发,且当鼠标在元素内移动或进入其子元素时也会触发。
-
支持事件冒泡,鼠标在元素及其子元素上的移动都会触发相应的事件,且事件会冒泡到父元素。
-
键盘事件
举例:
// 获取输入框元素const inputElement = document.getElementById(\'myInput\'); // 定义当按下回车时执行的函数function handleEnterPress(event) { if (event.keyCode === 13) { // 在这里编写你要执行的代码 console.log(\'回车键被按下了!\'); }} // 为输入框添加键盘事件监听器inputElement.addEventListener(\'keydown\', handleEnterPress);
表单事件
,
等)举例:
<!DOCTYPE html> <html lang=\"en\"> <head> <meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <title>表单事件示例</title> </head> <body> <form id=\"myForm\"> <label for=\"username\">用户名:</label> <input type=\"text\" id=\"username\" name=\"username\" required> <br> <label for=\"password\">密码:</label> <input type=\"password\" id=\"password\" name=\"password\" required> <br> <input type=\"submit\" value=\"提交\"> </form> <script src=\"script.js\"></script> </body> </html>
document.addEventListener(\'DOMContentLoaded\', function() { // 获取表单元素 var form = document.getElementById(\'myForm\'); // 为表单添加 submit 事件监听器 form.addEventListener(\'submit\', function(event) { // 阻止表单的默认提交行为,以便我们可以执行自定义操作 event.preventDefault(); // 验证表单输入(这里只是简单示例) var username = document.getElementById(\'username\').value; var password = document.getElementById(\'password\').value; if (username === \'\' || password === \'\') { alert(\'用户名和密码不能为空!\'); return; } // 假设验证通过,执行其他操作(例如,发送AJAX请求) console.log(\'表单数据:\', { username: username, password: password }); // 如果需要提交表单到服务器,可以取消注释下面的代码 // form.submit(); // 但在实际应用中,通常会使用AJAX来异步发送数据 }); });
窗口和文档事件
DOMContentLoaded 事件在 HTML 文档完全加载和解析后触发,不必等到样式表、图像等其他资源加载完成。因此,DOMContentLoaded 事件会比 load 事件早触发。
DOMContentLoaded 事件也是使用 addEventListener 方法来监听 。
其他事件
HTML 事件属性
鼠标事件 click 和 HTML 事件 onclick 的区别:
-
click
是 JavaScript 中的一个事件类型,是写在 JavaScript 代码中的document.getElementById(\"myButton\").addEventListener(\"click\", function() { alert(\"Button clicked!\");});
-
onclick
是一个 HTML 事件属性,是写在 HTML 元素标签中的<button id=\"myButton\" onclick=\"alert(\'Button clicked!\')\">Click me</button>
注意:
-
使用 addEventListener 可以给一个元素可以添加多个相同类型的事件处理函数
<template> <button id=\"test1\">测试</button></template><script setup>import { onMounted } from \'vue\';onMounted(() => { document.getElementById(\'test1\').addEventListener(\'click\', () => { console.log(1); }); document.getElementById(\'test1\').addEventListener(\'click\', () => { console.log(2); });});</script>
点击按钮会同时打印 1 和 2
-
但是一个元素只能有一个相同类型的 HTML 事件属性,重复会报错
Duplicate attribute
-
onload 属性可以用在
、
标签,不能用在、
、