资讯专栏INFORMATION COLUMN

JavaScript 编程精解 中文第三版 十五、处理事件

Clect / 324人阅读

摘要:事件与节点每个浏览器事件处理器被注册在上下文中。事件对象虽然目前为止我们忽略了它,事件处理器函数作为对象传递事件对象。若事件处理器不希望执行默认行为通常是因为已经处理了该事件,会调用事件对象的方法。

来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目

原文:Handling Events

译者:飞龙

协议:CC BY-NC-SA 4.0

自豪地采用谷歌翻译

部分参考了《JavaScript 编程精解(第 2 版)》

你对你的大脑拥有控制权,而不是外部事件。认识到这一点,你就找到了力量。

马可·奥勒留,《沉思录》

有些程序处理用户的直接输入,比如鼠标和键盘动作。这种输入方式不是组织整齐的数据结构 - 它是一次一个地,实时地出现的,并且期望程序在发生时作出响应。

事件处理器

想象一下,有一个接口,若想知道键盘上是否有一个键是否被按下,唯一的方法是读取那个按键的当前状态。为了能够响应按键动作,你需要不断读取键盘状态,以在按键被释放之前捕捉到按下状态。这种方法在执行时间密集计算时非常危险,因为你可能错过按键事件。

一些原始机器可以像那样处理输入。有一种更进一步的方法,硬件或操作系统发现按键时间并将其放入队列中。程序可以周期性地检查队列,等待新事件并在发现事件时进行响应。

当然,程序必须记得监视队列,并经常做这种事,因为任何时候,按键被按下和程序发现事件之间都会使得软件反应迟钝。该方法被称为轮询。大多数程序员更希望避免这种方法。

一个更好的机制是,系统在发生事件时主动通知我们的代码。浏览器实现了这种特性,支持我们将函数注册为特定事件的处理器。

Click this document to activate the handler.

window绑定指向浏览器提供的内置对象。 它代表包含文档的浏览器窗口。 调用它的addEventListener方法注册第二个参数,以便在第一个参数描述的事件发生时调用它。

事件与 DOM 节点

每个浏览器事件处理器被注册在上下文中。在为整个窗口注册处理器之前,我们在window对象上调用了addEventListener。 这种方法也可以在 DOM 元素和一些其他类型的对象上找到。 仅当事件发生在其注册对象的上下文中时,才调用事件监听器。


No handler here.

示例代码中将处理器附加到按钮节点上。因此,点击按钮时会触发并执行处理器,而点击文档的其他部分则没有反应。

向节点提供onclick属性也有类似效果。这适用于大多数类型的事件 - 您可以为属性附加处理器,属性名称为前面带有on的事件名称。

但是一个节点只能有一个onclick属性,所以你只能用这种方式为每个节点注册一个处理器。 addEventListener方法允许您添加任意数量的处理器,因此即使元素上已经存在另一个处理器,添加处理器也是安全的。

removeEventListener方法将删除一个处理器,使用类似于addEventListener的参数调用。


赋予removeEventListener的函数必须是赋予addEventListener的完全相同的函数值。 因此,要注销一个处理其,您需要为该函数提供一个名称(在本例中为once),以便能够将相同的函数值传递给这两个方法。

事件对象

虽然目前为止我们忽略了它,事件处理器函数作为对象传递:事件(Event)对象。这个对象持有事件的额外信息。例如,如果我们想知道哪个鼠标按键被按下,我们可以查看事件对象的which属性。


存储在各种类型事件对象中的信息是有差别的。随后本章将会讨论许多类型的事件。对象的type属性一般持有一个字符串,表示事件(例如"click""mousedown")。

传播

对于大多数事件类型,在具有子节点的节点上注册的处理器,也将接收发生在子节点中的事件。若点击一个段落中的按钮,段落的事件处理器也会收到点击事件。

但若段落和按钮都有事件处理器,则先执行最特殊的事件处理器(按钮的事件处理器)。也就是说事件向外传播,从触发事件的节点到其父节点,最后直到文档根节点。最后,当某个特定节点上注册的所有事件处理器按其顺序全部执行完毕后,窗口对象的事件处理器才有机会响应事件。

事件处理器任何时候都可以调用事件对象的stopPropagation方法,阻止事件进一步传播。该方法有时很实用,例如,你将一个按钮放在另一个可点击元素中,但你不希望点击该按钮会激活外部元素的点击行为。

下面的示例代码将mousedown处理器注册到按钮和其外部的段落节点上。在按钮上点击鼠标右键,按钮的处理器会调用stopPropagation,调度段落上的事件处理器执行。当点击鼠标其他键时,两个处理器都会执行。

A paragraph with a .

大多数事件对象都有target属性,指的是事件来源节点。你可以根据该属性防止无意中处理了传播自其他节点的事件。

我们也可以使用target属性来创建出特定类型事件的处理网络。例如,如果一个节点中包含了很长的按钮列表,比较方便的处理方式是在外部节点上注册一个点击事件处理器,并根据事件的target属性来区分用户按下了哪个按钮,而不是为每个按钮都注册独立的事件处理器。




默认动作

大多数事件都有与其关联的默认动作。若点击链接,就会跳转到链接目标。若点击向下的箭头,浏览器会向下翻页。若右击鼠标,可以得到一个上下文菜单等。

对于大多数类型的事件,JavaScript 事件处理器会在默认行为发生之前调用。若事件处理器不希望执行默认行为(通常是因为已经处理了该事件),会调用preventDefault事件对象的方法。

你可以实现你自己的键盘快捷键或交互式菜单。你也可以干扰用户期望的行为。例如,这里实现一个无法跳转的链接。

MDN

除非你有非常充足的理由,否则不要这样做。当预期的行为被打破时,使用你的页面的人会感到不快。

在有些浏览器中,你完全无法拦截某些事件。比如在 Chrome 中,关闭键盘快捷键(CTRL-WCOMMAND-W)无法由 JavaScript 处理。

按键事件

当按下键盘上的按键时,浏览器会触发"keydown"事件。当松开按键时,会触发"keyup"事件。

This page turns violet when you hold the V key.

尽管从keydown这个事件名上看应该是物理按键按下时触发,但当持续按下某个按键时,会循环触发该事件。有时,你想谨慎对待它。例如,如果您在按下某个按键时向 DOM 添加按钮,并且在释放按键时再次将其删除,则可能会在按住某个按键的时间过长时,意外添加数百个按钮。

该示例查看了事件对象的key属性,来查看事件关于哪个键。 该属性包含一个字符串,对于大多数键,它对应于按下该键时将键入的内容。 对于像Enter这样的特殊键,它包含一个用于命名键的字符串(在本例中为"Enter")。 如果你按住一个键的同时按住Shift键,这也可能影响键的名称 - "v"变为"V""1"可能变成"!",这是按下Shift-1键 在键盘上产生的东西。

诸如shiftctrlaltmeta(Mac 上的command)之类的修饰按键会像普通按键一样产生事件。但在查找组合键时,你也可以查看键盘和鼠标事件的shiftKeyctrlKeyaltKeymetaKey属性来判断这些键是否被按下。

Press Ctrl-Space to continue.

按键事件发生的 DOM 节点取决于按下按键时具有焦点的元素。 大多数节点不能拥有焦点,除非你给他们一个tabindex属性,但像链接,按钮和表单字段可以。 我们将在第 18 章中回顾表单字段。 当没有特别的焦点时,document.body充当按键事件的目标节点。

当用户键入文本时,使用按键事件来确定正在键入的内容是有问题的。 某些平台,尤其是 Android 手机上的虚拟键盘,不会触发按键事件。 但即使你有一个老式键盘,某些类型的文本输入也不能直接匹配按键,例如其脚本不适合键盘的人所使用的 IME(“输入法编辑器”)软件 ,其中组合多个热键来创建字符。

要注意什么时候输入了内容,每当用户更改其内容时,可以键入的元素(例如

undefined传递给clearTimeout或在一个已结束的定时器上调用clearTimeout是没有效果的。因此,我们不需要关心何时调用该方法,只需要每个事件中都这样做即可。

如果我们想要保证每次响应之间至少间隔一段时间,但不希望每次事件发生时都重置定时器,而是在一连串事件连续发生时能够定时触发响应,那么我们可以使用一个略有区别的方法来解决问题。例如,我们想要响应"mousemove"事件来显示当前鼠标坐标,但频率只有 250ms。

本章小结

事件处理器可以检测并响应发生在我们的 Web 页面上的事件。addEventListener方法用于注册处理器。

每个事件都有标识事件的类型(keydownfocus等)。大多数方法都会在特定 DOM 元素上调用,接着向其父节点传播,允许每个父元素的处理器都能处理这些事件。

JavaScript 调用事件处理器时,会传递一个包含事件额外信息的事件对象。该对象也有方法支持停止进一步传播(stopPropagation),也支持阻止浏览器执行事件的默认处理器(preventDefault)。

按下键盘按键时会触发keydownkeyup事件。按下鼠标按钮时,会触发mousedownmouseupclick事件。移动鼠标会触发mousemove事件。触摸屏交互会导致"touchstart""touchmove""touchend"事件。

我们可以通过scroll事件监测滚动行为,可以通过focusblur事件监控焦点改变。当文档完成加载后,会触发窗口的load事件。

习题 气球

编写一个显示气球的页面(使用气球 emoji,ud83cudf88)。 当你按下上箭头时,它应该变大(膨胀)10%,而当你按下下箭头时,它应该缩小(放气)10%。

您可以通过在其父元素上设置font-size CSS 属性(style.fontSize)来控制文本大小(emoji 是文本)。 请记住在该值中包含一个单位,例如像素(10px)。

箭头键的键名是"ArrowUp""ArrowDown"。确保按键只更改气球,而不滚动页面。

实现了之后,添加一个功能,如果你将气球吹过一定的尺寸,它就会爆炸。 在这种情况下,爆炸意味着将其替换为“爆炸 emoji,ud83dudca5”,并且移除事件处理器(以便您不能使爆炸变大变小)。

💥

鼠标轨迹

在 JavaScript 早期,有许多主页都会在页面上使用大量的动画,人们想出了许多该语言的创造性用法。

其中一种是“鼠标踪迹”,也就是一系列的元素,随着你在页面上移动鼠标,它会跟着你的鼠标指针。

在本习题中实现鼠标轨迹的功能。使用绝对定位、固定尺寸的

元素,背景为黑色(请参考鼠标点击一节中的示例)。创建一系列此类元素,当鼠标移动时,伴随鼠标指针显示它们。

有许多方案可以实现我们所需的功能。你可以根据你的需要实现简单的或复杂的方法。简单的解决方案是保存固定鼠标的轨迹元素并循环使用它们,每次mousemove事件触发时将下一个元素移动到鼠标当前位置。



选项卡

选项卡面板广泛用于用户界面。它支持用户通过选择元素上方的很多突出的选项卡来选择一个面板。

本习题中,你必须实现一个简单的选项卡界面。编写asTabs函数,接受一个 DOM 节点并创建选项卡界面来展现该节点的子元素。该函数应该在顶层节点中插入大量

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/105048.html

相关文章

  • JavaScript 编程精解 中文三版 十九、项目:像素艺术编辑器

    摘要:相反,当响应指针事件时,它会调用创建它的代码提供的回调函数,该函数将处理应用的特定部分。回调函数可能会返回另一个回调函数,以便在按下按钮并且将指针移动到另一个像素时得到通知。它们为组件构造器的数组而提供。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Project: A Pixel Art Editor 译者:飞龙 协议:CC BY-NC-SA 4...

    Meils 评论0 收藏0
  • JavaScript 编程精解 中文三版 零、前言

    摘要:来源编程精解中文第三版翻译项目原文译者飞龙协议自豪地采用谷歌翻译部分参考了编程精解第版,这是一本关于指导电脑的书。在可控的范围内编写程序是编程过程中首要解决的问题。我们可以用中文来描述这些指令将数字存储在内存地址中的位置。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Introduction 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地...

    sanyang 评论0 收藏0
  • JavaScript 编程精解 中文三版 二、程序结构

    摘要:为了运行包裹的程序,可以将这些值应用于它们。在浏览器中,输出出现在控制台中。在英文版页面上运行示例或自己的代码时,会在示例之后显示输出,而不是在浏览器的控制台中显示。这被称为条件执行。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Program Structure 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《J...

    ThinkSNS 评论0 收藏0
  • JavaScript 编程精解 中文三版 十三、浏览器中的 JavaScript

    摘要:在本例中,使用属性指定链接的目标,其中表示超文本链接。您应该认为和元数据隐式出现在示例中,即使它们没有实际显示在文本中。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:JavaScript and the Browser 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《JavaScript 编程精解(第 2 版)》 ...

    zhiwei 评论0 收藏0
  • JavaScript 编程精解 中文三版 一、值,类型和运算符

    摘要:来源编程精解中文第三版翻译项目原文译者飞龙协议自豪地采用谷歌翻译部分参考了编程精解第版在机器的表面之下,程序在运转。本章将会介绍程序当中的基本元素,包括简单的值类型以及值运算符。示例中的乘法运算符优先级高于加法。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Values, Types, and Operators 译者:飞龙 协议:CC BY-NC...

    wh469012917 评论0 收藏0

发表评论

0条评论

Clect

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<