20 分钟全面理解 JavaScript 事件机制

简介

事件是由用户或浏览器本身发起的发生在浏览器中的动作。以下示例为发生在网站上的一些常见事件:

  • 页面完成加载

  • 用户点击按钮

  • 用户将鼠标悬停在下拉菜单上

  • 用户提交表单

  • 用户按下键盘上的键

通过编写执行事件的JavaScript响应代码,开发人员可以向用户显示消息、验证数据、对按钮单击做出反应以及许多其他操作。

本文将介绍事件处理程序、事件侦听器和事件对象。还将介绍三种不同的方式来处理事件,以及一些最常见的事件。了解事件可以帮助开发人员为用户提供更具交互性的web体验。

事件处理程序(Event Handlers)和事件侦听器(Event Listeners)

当用户单击按钮或按下某个键时,会触发事件。分别称为点击事件和按键事件。

事件处理程序是在事件触发时运行的JavaScript函数。

事件侦听器附加响应式接口到元素,允许特定元素等待并“侦听”给定事件的触发。

将事件分配给元素的三种方法:

  • 内联事件处理程序

  • 事件处理程序属性

  • 事件监听器

下面我们将一一介绍这三种方法的优缺点。

内联事件处理程序属性

要学习事件处理程序,首先要了解内联事件处理程序。让我们从一个由button元素和p元素组成的基本示例开始:用户单击按钮时更改p的文本内容。

events.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>

直接在按钮上添加onclick属性。属性值是我们创建的名为changeText()的函数。

events.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.”:

内联事件处理程序有助于直接理解事件,但通常用于测试和教学演示,正式项目中不推荐使用。

事件处理程序属性

事件处理程序属性与内联处理程序非常相似,除了一点,我们在JavaScript中设置元素的属性,而不是在HTML中设置属性。

此处的设置相同,只是不再在标记中包含onclick="changeText()"

events.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代码所遵循的驼峰式命名规则。注意是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()是最后一个添加到onclick属性中的。

事件监听器

事件侦听器监视元素上的事件。我们将使用addEventListener()方法来侦听事件,而并不是将事件直接分配给元素上的属性。

addEventListener()有两个必要参数——要监听的事件和监听器回调函数。

事件侦听器的HTML将与前面的示例相同。

events.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);

上面的两个事件都将触发:首先弹出提示框,一旦点击关闭提示框后便修改p元素的内容。

通常,我们使用匿名函数替代事件侦听器上的函数引用。匿名函数是未命名的函数。

// 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中处理事件最常用的首选方式。

常用事件

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

鼠标事件

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

事件描述
click在元素上按下和释放鼠标时触发
dblclick双击元素时触发
mouseenter当鼠标进入元素时触发
mouseleave当鼠标离开元素时触发
mousemove每当鼠标在元素内移动时触发

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

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

表单事件

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

事件描述
submit提交表单时触发
focus当元素获得焦点时触发
blur当元素失去焦点时触发

当元素被选中时,例如,通过鼠标单击或TAB键导航到元素时,将获得焦点。

使用JavaScript发送表单的优点是提交表单时不需要重新加载页面,并且可以使用JavaScript来验证所需的输入字段。

键盘事件

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

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

虽然键盘事件看起来很相似,但keydownkeypress事件访问的键并不所有完全相同。keydown将确认按下的每个键,而keypress将忽略不产生字符的键,例如SHIFTALT以及DELETE

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

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

例如,如果用户按下键盘上的字母a键,则与该键相关的以下属性将浮出水面:

属性描述示例
key表示字符名称a
code表示被按下的物理键KeyA

为了展示如何通过JavaScript控制台收集这些信息,我们编写以下代码行。

// Test the key and code properties
document.addEventListener('keydown', event => {
 console.log('key: ' + event.key);
 console.log('code: ' + event.code);
});

一旦我们在控制台按下ENTER键,就可以在键盘上按键,在本例中,按的是a

Output
key: a
code: KeyA

key属性是字符的名称,可以改变——例如,按下SHIFTa会变成A。而code属性表示的是键盘上的物理键。

事件对象

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

Event对象通过侦听器函数作为参数传递,通常写作evente。我们可以访问keydown事件的code属性来复制PC游戏的键盘控件。

创建一个带有<p>标记的基本HTML文件并将其加载到浏览器中。

event-test-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;
 }
});

当你按下其中一个键(asdw)时,将看到类似以下内容的输出:

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

继续介绍最常用的事件属性之一:target属性。在下面的示例中,在section中有三个div元素。

event-test-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>

通过在浏览器的开发者控制台中使用event.target,我们可以将事件侦听器放置在外部section元素上,并获取嵌套最深的元素。

const section = document.querySelector('section');

// Print the selected target
section.addEventListener('click', event => {
 console.log(event.target);
});

单击其中任何一个元素都会返回相关特定元素的输出到控制台。这非常有用,因为你只需要放置一个事件侦听器,就可以访问许多嵌套元素。

总结

事件是发生在网站上的操作,例如单击、悬停、提交表单、加载页面或按下键盘上的键。当我们能够让网站响应用户采取的行动时,JavaScript才真正变得交互性和动态性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾月拾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值