介绍
在了解DOM系列中,我们讨论了DOM树以及如何使用开发人员工具控制台 访问 , 遍历 , 添加和删除以及修改节点和元素。
尽管在这一点上,我们现在可以对DOM所做的任何更改进行修改,但从用户角度来看,它并不是非常有用,因为我们只手动触发更改。 通过了解事件,我们将了解如何将所有事情联系在一起以制作互动网站。
事件是在浏览器中发生的操作,可以由用户或浏览器本身启动。 以下是一些可能发生在网站上的常见事件的例子:
- 该页面完成加载
- 用户点击一个按钮
- 用户悬停在下拉列表中
- 用户提交表单
- 用户按下键盘上的按键
通过对事件执行的JavaScript响应进行编码,开发人员可以向用户显示消息,验证数据,响应按钮点击以及其他许多操作。
在本文中,我们将介绍事件处理程序,事件监听器和事件对象。 我们还将通过三种不同的方式编写代码来处理事件,以及一些最常见的事件。 通过了解事件,您可以为最终用户提供更具互动性的网络体验。
事件处理程序和事件监听器
当用户点击一个按钮或按下某个键时,会触发一个事件。 这些分别称为点击事件或按键事件。
事件处理程序是一个JavaScript函数,在事件触发时运行。
一个事件监听器将一个响应接口附加到一个元素上,该元素允许该特定元素等待并“监听”给定事件触发。
有三种方法可以将事件分配给元素:
- 内联事件处理程序
- 事件处理器属性
- 事件监听器
我们将通过三种方法来确保您熟悉事件触发的每种方式,然后讨论每种方法的优缺点。
内联事件处理程序属性
要开始了解事件处理程序,我们将首先考虑内联事件处理程序 。 让我们从一个非常基本的例子开始,它由一个button
元素和一个p
元素组成。 我们希望用户单击button
来更改p
的文本内容。
我们从一个带有按钮的HTML页面开始。 我们将引用一个JavaScript文件,我们稍后将添加代码。
<!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()
的函数。
<!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
。
// 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.
, I changed because of an inline event handler.
:
内联事件处理程序是开始理解事件的直接方式,但它们通常不应超出测试和教育目的。
您可以比较内联事件处理程序以在HTML元素上嵌入CSS样式。 维护一个单独的类样式表比在每个元素上创建内联样式要实用得多,正如维护完全通过单独的脚本文件处理JavaScript而不是为每个元素添加处理程序一样。
事件处理程序属性
内联事件处理程序的下一步是事件处理程序属性 。 这与内联处理程序非常类似,只不过我们使用JavaScript设置元素的属性而不是HTML中的属性。
除了我们不再在标记中包含onclick="changeText()"
之外,这里的设置将与此相同:
...
<body>
<button>Click me</button>
<p>I will change.</p>
</body>
...
我们的函数也会保持相似,除了现在我们需要访问JavaScript中的button
元素。 我们可以简单地访问onclick
就像访问style
或id
或任何其他元素属性一样,然后分配函数引用。
// 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
属性会导致除最后一个之外的所有其他内容被覆盖,如下所示。
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将和前面的例子一样。
...
<button>Click me</button>
<p>I will change.</p>
...
我们仍将使用与之前相同的changeText()
函数。 我们将addEventListener()
方法附加到按钮上。
// 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
。 每个事件监听者都会从单词中删除。 在下一节中,我们将看到更多其他类型事件的例子。
当您使用上面的JavaScript代码重新加载页面时,您会收到以下输出:
首先看,事件监听器看起来与事件处理器属性非常相似,但它们有一些优点。 我们可以在同一个元素上设置多个事件监听器,如下例所示。
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中还有很多事件。 我们将在下面介绍几个最常见的事件。
鼠标事件
鼠标事件是最常用的事件之一。 它们是指涉及鼠标上的单击按钮或悬停和移动鼠标指针的事件。 这些事件也对应于Touch设备上的等效操作。
事件 | 描述 |
---|---|
click |
当鼠标按下并释放元素时触发 |
dblclick |
点击两次元素时触发 |
mouseenter |
当指针进入元素时触发 |
mouseleave |
当指针离开元素时触发 |
mousemove |
每次指针在元素内移动时触发 |
click
是一个复合事件,它由组合的mousedown
和mouseup
事件组成,分别当鼠标按钮被按下或抬起时触发。
只要鼠标指针位于元素上,使用mouseenter
和mouseleave
一起重新创建悬停效果。
表单事件
表单事件是与表单相关的操作,如正在选择或未选中的input
元素以及正在提交的表单。
事件 | 描述 |
---|---|
submit |
提交表单时触发 |
focus |
当元素(如输入)获得焦点时触发 |
blur |
元素失去焦点时触发 |
选择某个元素时可实现焦点 ,例如,通过鼠标单击或通过TAB
键导航到该元素。
JavaScript通常用于提交表单并将值发送到后端语言。 使用JavaScript发送表单的优点是它不需要页面重新加载来提交表单,并且JavaScript可以用于验证所需的输入字段。
键盘事件
键盘事件用于处理键盘操作,例如按下按键,抬起按键并按住按键。
事件 | 描述 |
---|---|
keydown |
按下某个键时触发一次 |
keyup |
当钥匙被释放时发射一次 |
keypress |
按下键时持续闪光 |
尽管它们看起来很相似,但keydown
和keypress
事件不能访问所有完全相同的密钥。 虽然keydown
会确认每个按下的keypress
,但keypress
将省略不产生字符的keypress
,如SHIFT
, ALT
或DELETE
。
键盘事件具有访问各个键的特定属性。
如果将一个称为event
对象的参数传递给事件监听器,则可以访问有关发生的操作的更多信息。 与键盘对象有关的三个属性包括keyCode
, key
和code
。
例如,如果用户在他们的键盘上按下字母键,那么与该键有关的以下属性将会显示:
属性 | 描述 | 例 |
---|---|---|
keyCode |
一个关键的数字 | 65 |
key |
代表角色名称 | 一个 |
code |
代表被按下的物理键 | 科亚 |
为了展示如何通过JavaScript控制台收集这些信息,我们可以编写以下几行代码。
// Test the keyCode, key, and code properties
document.addEventListener('keydown', event => {
console.log('key: ' + event.keyCode);
console.log('key: ' + event.key);
console.log('code: ' + event.code);
});
一旦我们按下控制台上的ENTER
,我们现在就可以按下键盘上的一个键,在这个例子中,我们将按下a
键。
OutputkeyCode: 65
key: a
code: KeyA
keyCode
属性是一个与已被按下的键有关的数字。 key
属性是可以更改的字符的名称 - 例如,使用SHIFT
按a
会导致A
的key
。 code
属性表示键盘上的物理键。
请注意, keyCode
正在被弃用,并且最好在新项目中使用code
。
要了解更多信息,您可以在Mozilla开发者网络上查看完整的事件列表 。
事件对象
Event
对象由所有事件可以访问的属性和方法组成。 除了通用的Event
对象外,每种类型的事件都有其自己的扩展,如KeyboardEvent
和MouseEvent
。
Event
对象作为参数传递给监听器函数。 它通常写作event
或e
。 我们可以访问keydown
事件的code
属性来复制PC游戏的键盘控件。
要试用它,请使用<p>
标签创建一个基本的HTML文件并将其加载到浏览器中。
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Events</title>
</head>
<body>
<p></p>
</body>
</html>
然后,在浏览器的开发者控制台中输入以下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
元素。
<!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
对象。 利用这些知识,您将能够开始制作动态网站和应用程序。