介绍
在了解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 对象。 使用这些知识,您将能够开始制作动态网站和应用程序。