了解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 元素。 我们可以像访问 styleid 或任何其他元素属性一样简单地访问 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);

此外,您可以在 documentwindow 对象上使用 addEventListener()

事件侦听器是目前在 JavaScript 中处理事件的最常见和首选的方式。

常见事件

我们已经了解了使用 click 事件的内联事件处理程序、事件处理程序属性和事件侦听器,但 JavaScript 中还有更多事件。 我们将在下面讨论一些最常见的事件。

鼠标事件

鼠标事件是最常用的事件之一。 它们指的是涉及单击鼠标按钮或悬停和移动鼠标指针的事件。 这些事件也对应于触摸设备上的等效操作。

事件 描述
click 当鼠标在元素上按下和释放时触发
dblclick 当一个元素被点击两次时触发
mouseenter 当指针进入元素时触发
mouseleave 当指针离开元素时触发
mousemove 每次指针在元素内移动时触发

click 是一个复合事件,由组合的 mousedownmouseup 事件组成,分别在按下或抬起鼠标按钮时触发。

串联使用 mouseentermouseleave 可重新创建悬停效果,只要鼠标指针位于元素上,该效果就会持续。

表单事件

表单事件是与表单相关的操作,例如选择或取消选择 input 元素以及提交表单。

事件 描述
submit 提交表单时触发
focus 当元素(例如输入)获得焦点时触发
blur 当元素失去焦点时触发

Focus 是在选择一个元素时实现的,例如,通过鼠标单击或通过 TAB 键导航到它。

JavaScript 通常用于提交表单并将值发送到后端语言。 使用 JavaScript 发送表单的优点是提交表单时不需要重新加载页面,并且可以使用 JavaScript 来验证所需的输入字段。

键盘事件

键盘事件用于处理键盘动作,例如按下键、抬起键和按住键。

事件 描述
keydown 按下键时触发一次
keyup 释放键时触发一次
keypress 按键时连续触发

尽管它们看起来相似,但 keydownkeypress 事件不会访问所有完全相同的键。 虽然 keydown 将确认按下的每个键,但 keypress 将省略不产生字符的键,例如 SHIFTALT 或 [X151X ]。

键盘事件具有用于访问单个键的特定属性。

如果将一个称为 event 对象的参数传递给事件侦听器,我们可以访问有关所发生操作的更多信息。 与键盘对象相关的两个属性包括 keycode

例如,如果用户在其键盘上按下字母 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 属性是角色的名称,可以更改 - 例如,将 aSHIFT 一起按会导致 keyAcode 属性表示键盘上的物理键。

要了解更多信息,您可以查看 Mozilla 开发者网络 上的 完整事件列表。

事件对象

Event 对象由所有事件都可以访问的属性和方法组成。 除了通用的 Event 对象外,每种类型的事件都有自己的扩展,例如 KeyboardEventMouseEvent

Event 对象作为参数通过侦听器函数传递。 它通常写为 evente。 我们可以访问 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;
    }
});

当您按下其中一个键 - asdw - 您将看到类似于以下内容的输出:

从这里开始,您可以继续开发浏览器如何响应以及用户按下这些键的方式,并可以创建一个更加动态的网站。

接下来,我们将介绍最常用的事件属性之一: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 对象。 使用这些知识,您将能够开始制作动态网站和应用程序。