了解JavaScript中的事件
介绍
在了解DOM系列中,我们讨论了DOM树以及如何访问、遍历、添加和删除 和 使用 开发者工具控制台 修改 节点和元素。
尽管此时我们现在几乎可以对 DOM 进行任何我们想要的更改,但从用户的角度来看,这并不是很有帮助,因为我们只是手动触发了更改。 通过了解事件,我们将了解如何将所有内容联系在一起以制作交互式网站。
Events 是发生在浏览器中的动作,可由用户或浏览器本身发起。 以下是网站上可能发生的一些常见事件示例:
- 页面完成加载
- 用户点击一个按钮
- 用户将鼠标悬停在下拉菜单上
- 用户提交表单
- 用户按下键盘上的一个键
通过对事件执行的 JavaScript 响应进行编码,开发人员可以向用户显示消息、验证数据、对按钮单击做出反应以及许多其他操作。
在本文中,我们将介绍事件处理程序、事件侦听器和事件对象。 我们还将介绍三种不同的方式来编写代码来处理事件,以及一些最常见的事件。 通过了解事件,您将能够为最终用户提供更具交互性的 Web 体验。
事件处理程序和事件侦听器
当用户单击按钮或按下某个键时,会触发一个事件。 这些分别称为点击事件或按键事件。
事件处理程序 是一个在事件触发时运行的 JavaScript 函数。
事件侦听器 将响应式接口附加到元素,这允许该特定元素等待并“侦听”给定事件的触发。
将事件分配给元素的三种方法:
- 内联事件处理程序
- 事件处理程序属性
- 事件监听器
我们将介绍所有三种方法,以确保您熟悉触发事件的每种方式,然后讨论每种方法的优缺点。
内联事件处理程序属性
要开始了解事件处理程序,我们将首先考虑 内联事件处理程序 。 让我们从一个非常基本的示例开始,它由一个 button
元素和一个 p
元素组成。 我们希望用户点击button
来改变p
的文本内容。
让我们从正文中带有按钮的 HTML 页面开始。 我们将引用一个 JavaScript 文件,稍后我们将添加代码。
事件.html
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <!-- Add button --> <button>Click me</button> <p>Try to change me.</p> </body> <!-- Reference JavaScript file --> <script src="js/events.js"></script> </html>
直接在 button
上,我们将添加一个名为 onclick
的属性。 属性值将是我们创建的名为 changeText()
的函数。
事件.html
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <button onclick="changeText()">Click me</button> <p>Try to change me.</p> </body> <script src="js/events.js"></script> </html>
让我们创建我们的 events.js
文件,我们将其放置在此处的 js/
目录中。 在其中,我们将创建 changeText()
函数,它将修改 p
元素的 textContent
。
js/events.js
// Function to modify the text content of the paragraph const changeText = () => { const p = document.querySelector('p'); p.textContent = "I changed because of an inline event handler."; }
当您第一次加载 events.html
时,您会看到如下所示的页面:
但是,当您或其他用户单击按钮时,p
标签的文本将从 Try to change me.
变为 I changed because of an inline event handler.
:
内联事件处理程序是开始理解事件的一种直接方式,但通常不应将它们用于测试和教育目的之外。
您可以将内联事件处理程序与 HTML 元素上的内联 CSS 样式进行比较。 维护一个单独的类样式表比在每个元素上创建内联样式更实用,就像维护完全通过单独的脚本文件处理的 JavaScript 比为每个元素添加处理程序更可行一样。
事件处理程序属性
内联事件处理程序的下一步是 事件处理程序属性 。 这与内联处理程序非常相似,只是我们在 JavaScript 中设置元素的属性,而不是在 HTML 中设置属性。
此处的设置将相同,只是我们不再在标记中包含 onclick="changeText()"
:
事件.html
... <body> <button>Click me</button> <p>I will change.</p> </body> ...
我们的函数也将保持相似,除了现在我们需要访问 JavaScript 中的 button
元素。 我们可以像访问 style
或 id
或任何其他元素属性一样简单地访问 onclick
,然后分配函数引用。
js/events.js
// Function to modify the text content of the paragraph const changeText = () => { const p = document.querySelector('p'); p.textContent = "I changed because of an event handler property."; } // Add event handler as a property of the button element const button = document.querySelector('button'); button.onclick = changeText;
注意: 事件处理程序不遵循大多数 JavaScript 代码所遵循的 camelCase 约定。 请注意,代码是 onclick
,而不是 onClick
。
首次加载页面时,浏览器将显示以下内容:
现在,当您单击按钮时,它将具有与以前类似的效果:
请注意,当将函数引用传递给 onclick
属性时,我们不包括括号,因为此时我们没有调用函数,而只是传递了对它的引用。
事件处理程序属性比内联处理程序更易于维护,但它仍然存在一些相同的障碍。 例如,尝试设置多个单独的 onclick
属性将导致除最后一个之外的所有属性都被覆盖,如下所示。
js/events.js
const p = document.querySelector('p'); const button = document.querySelector('button'); const changeText = () => { p.textContent = "Will I change?"; } const alertText = () => { alert('Will I alert?'); } // Events can be overwritten button.onclick = changeText; button.onclick = alertText;
在上面的示例中,单击 button
只会显示警报,不会更改 p
文本,因为 alert()
代码是添加到属性中的最后一个代码。
了解内联事件处理程序和事件处理程序属性后,让我们继续讨论事件侦听器。
事件监听器
JavaScript 事件处理程序的最新成员是事件侦听器。 事件侦听器 监视元素上的事件。 我们将使用 addEventListener()
方法来监听事件,而不是将事件直接分配给元素上的属性。
addEventListener()
有两个强制参数——它要监听的事件和监听器回调函数。
我们的事件侦听器的 HTML 将与前面的示例相同。
事件.html
... <button>Click me</button> <p>I will change.</p> ...
我们仍将使用与以前相同的 changeText()
函数。 我们将 addEventListener()
方法附加到按钮上。
js/events.js
// Function to modify the text content of the paragraph const changeText = () => { const p = document.querySelector('p'); p.textContent = "I changed because of an event listener."; } // Listen for click event const button = document.querySelector('button'); button.addEventListener('click', changeText);
请注意,对于前两种方法,单击事件被称为 onclick
,但对于事件侦听器,它被称为 click
。 每个事件侦听器都会从单词中删除 on
。 在下一节中,我们将查看更多其他类型事件的示例。
当您使用上面的 JavaScript 代码重新加载页面时,您将收到以下输出:
乍一看,事件侦听器似乎与事件处理程序属性非常相似,但它们有一些优点。 我们可以在同一个元素上设置多个事件监听器,如下例所示。
js/events.js
const p = document.querySelector('p'); const button = document.querySelector('button'); const changeText = () => { p.textContent = "Will I change?"; } const alertText = () => { alert('Will I alert?'); } // Multiple listeners can be added to the same event and element button.addEventListener('click', changeText); button.addEventListener('click', alertText);
在这个例子中,这两个事件都会触发,一旦点击离开警报,就会为用户提供警报和修改后的文本。
通常,将使用匿名函数而不是事件侦听器上的函数引用。 匿名函数是未命名的函数。
// An anonymous function on an event listener button.addEventListener('click', () => { p.textContent = "Will I change?"; });
也可以使用 removeEventListener()
函数从元素中删除一个或所有事件。
// Remove alert function from button element button.removeEventListener('click', alertText);
此外,您可以在 document
和 window
对象上使用 addEventListener()
。
事件侦听器是目前在 JavaScript 中处理事件的最常见和首选的方式。
常见事件
我们已经了解了使用 click 事件的内联事件处理程序、事件处理程序属性和事件侦听器,但 JavaScript 中还有更多事件。 我们将在下面讨论一些最常见的事件。
鼠标事件
鼠标事件是最常用的事件之一。 它们指的是涉及单击鼠标按钮或悬停和移动鼠标指针的事件。 这些事件也对应于触摸设备上的等效操作。
事件 | 描述 |
---|---|
click
|
当鼠标在元素上按下和释放时触发 |
dblclick
|
当一个元素被点击两次时触发 |
mouseenter
|
当指针进入元素时触发 |
mouseleave
|
当指针离开元素时触发 |
mousemove
|
每次指针在元素内移动时触发 |
click
是一个复合事件,由组合的 mousedown
和 mouseup
事件组成,分别在按下或抬起鼠标按钮时触发。
串联使用 mouseenter
和 mouseleave
可重新创建悬停效果,只要鼠标指针位于元素上,该效果就会持续。
表单事件
表单事件是与表单相关的操作,例如选择或取消选择 input
元素以及提交表单。
事件 | 描述 |
---|---|
submit
|
提交表单时触发 |
focus
|
当元素(例如输入)获得焦点时触发 |
blur
|
当元素失去焦点时触发 |
Focus 是在选择一个元素时实现的,例如,通过鼠标单击或通过 TAB
键导航到它。
JavaScript 通常用于提交表单并将值发送到后端语言。 使用 JavaScript 发送表单的优点是提交表单时不需要重新加载页面,并且可以使用 JavaScript 来验证所需的输入字段。
键盘事件
键盘事件用于处理键盘动作,例如按下键、抬起键和按住键。
事件 | 描述 |
---|---|
keydown
|
按下键时触发一次 |
keyup
|
释放键时触发一次 |
keypress
|
按键时连续触发 |
尽管它们看起来相似,但 keydown
和 keypress
事件不会访问所有完全相同的键。 虽然 keydown
将确认按下的每个键,但 keypress
将省略不产生字符的键,例如 SHIFT
、ALT
或 [X151X ]。
键盘事件具有用于访问单个键的特定属性。
如果将一个称为 event
对象的参数传递给事件侦听器,我们可以访问有关所发生操作的更多信息。 与键盘对象相关的两个属性包括 key
和 code
。
例如,如果用户在其键盘上按下字母 a
键,则与该键相关的以下属性将出现:
财产 | 描述 | 例子 |
---|---|---|
key
|
代表角色名称 | a |
code
|
表示被按下的物理键 | 键A |
为了展示如何通过 JavaScript 控制台收集这些信息,我们可以编写以下代码行。
// Test the key and code properties document.addEventListener('keydown', event => { console.log('key: ' + event.key); console.log('code: ' + event.code); });
一旦我们在控制台上按下 ENTER
,我们现在可以按下键盘上的一个键,在这个例子中,我们将按下 a
。
Outputkey: a code: KeyA
key
属性是角色的名称,可以更改 - 例如,将 a
与 SHIFT
一起按会导致 key
为 A
。 code
属性表示键盘上的物理键。
要了解更多信息,您可以查看 Mozilla 开发者网络 上的 完整事件列表。
事件对象
Event
对象由所有事件都可以访问的属性和方法组成。 除了通用的 Event
对象外,每种类型的事件都有自己的扩展,例如 KeyboardEvent
和 MouseEvent
。
Event
对象作为参数通过侦听器函数传递。 它通常写为 event
或 e
。 我们可以访问 keydown
事件的 code
属性来复制 PC 游戏的键盘控制。
要试用它,请创建一个带有 <p>
标记的基本 HTML 文件并将其加载到浏览器中。
事件测试-p.html
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <p></p> </body> </html>
然后,在浏览器的 Developer Console 中键入以下 JavaScript 代码。
// Pass an event through to a listener document.addEventListener('keydown', event => { var element = document.querySelector('p'); // Set variables for keydown codes var a = 'KeyA'; var s = 'KeyS'; var d = 'KeyD'; var w = 'KeyW'; // Set a direction for each code switch (event.code) { case a: element.textContent = 'Left'; break; case s: element.textContent = 'Down'; break; case d: element.textContent = 'Right'; break; case w: element.textContent = 'Up'; break; } });
当您按下其中一个键 - a
、s
、d
或 w
- 您将看到类似于以下内容的输出:
从这里开始,您可以继续开发浏览器如何响应以及用户按下这些键的方式,并可以创建一个更加动态的网站。
接下来,我们将介绍最常用的事件属性之一:target
属性。 在以下示例中,我们在一个 section
中包含三个 div
元素。
事件测试div.html
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <section> <div id="one">One</div> <div id="two">Two</div> <div id="three">Three</div> </section> </body> </html>
在浏览器的开发者控制台中使用带有 JavaScript 的 event.target
,我们可以在外部 section
元素上放置一个事件侦听器,并获得嵌套最深的元素。
const section = document.querySelector('section'); // Print the selected target section.addEventListener('click', event => { console.log(event.target); });
单击其中任何一个元素将使用 event.target
将相关特定元素的输出返回到控制台。 这非常有用,因为它只允许您放置一个可用于访问许多嵌套元素的事件侦听器。
使用 Event
对象,我们可以设置与所有事件相关的响应,包括通用事件和更具体的扩展。
结论
事件是发生在网站上的操作,例如单击、悬停、提交表单、加载页面或按下键盘上的键。 当我们能够让网站响应用户采取的行动时,JavaScript 变得真正具有交互性和动态性。
在本教程中,我们了解了什么是事件、常见事件的示例、事件处理程序和事件侦听器之间的区别以及如何访问 Event
对象。 使用这些知识,您将能够开始制作动态网站和应用程序。