此文是W3C UI Events标准的阅读笔记。UI Events是一些列预定好的[DOM]事件,主要用来跟用户交互。

W3C UI Events阅读笔记

事件类型

4. Event Types

输入事件(Input Events)

输入事件是指DOM被用户操作修改之后所发送的通知。定义如下:

[Constructor(DOMString type, optional InputEventInit eventInitDict), Exposed=Window]
interface InputEvent : UIEvent {
  readonly attribute DOMString? data;
  readonly attribute boolean isComposing;
  readonly attribute DOMString inputType;
};
  • data存储这输入法产生的数据
  • isComposing用来指示当前的输入法拼接过程是否结束
  • inputType用来指示输入的类型,见Input Events Level 1

输入事件只有两种:

  • beforeinput
  • input

键盘事件(Keyboard Events)

键盘事件跟设备相关(这里的设备大概就是指键盘咯)。它们依赖于操作系统如果处理键盘事件。通常操作系统会指定和识别若干种预置类型的键盘,然后键盘厂商通过驱动去匹配这些键盘类型。除此之外,操作系统又会根据区域语言的不同,来对一种硬盘类型使用不同的键盘映射表。这里面有两层抽象,键盘产生的是扫描码,然后操作系统将扫描码转换成虚拟码。一种键盘类型规定了这个键盘会产生什么样的扫描码,而键盘映射表则决定如果将这些扫描码转化成虚拟码。最终应用程序接收到的是虚拟码。

键盘事件定义:

[Constructor(DOMString type, optional KeyboardEventInit eventInitDict), Exposed=Window]
interface KeyboardEvent : UIEvent {
  // KeyLocationCode
  const unsigned long DOM_KEY_LOCATION_STANDARD = 0x00;
  const unsigned long DOM_KEY_LOCATION_LEFT = 0x01;
  const unsigned long DOM_KEY_LOCATION_RIGHT = 0x02;
  const unsigned long DOM_KEY_LOCATION_NUMPAD = 0x03;

  readonly attribute DOMString key;
  readonly attribute DOMString code;
  readonly attribute unsigned long location;

  readonly attribute boolean ctrlKey;
  readonly attribute boolean shiftKey;
  readonly attribute boolean altKey;
  readonly attribute boolean metaKey;

  readonly attribute boolean repeat;
  readonly attribute boolean isComposing;

  boolean getModifierState(DOMString keyArg);
};

解释一卡其中的某些字段:

  • key用来区分键盘码(就是键盘上的按键),而code用来区分虚拟码(按键产生的值)。一个虚拟码,比如ALT,可以由左ALT键产生,也可以由右ALT键产生。location可以用来区分具体键的位置。
  • repeat表明键被按住,然后不断发送虚拟码,每次会按顺序产生三个事件keydown, beforeinput, input
  • isComposing表明输入法正在合成字符

默认情况下键的location必须是DOM_KEY_LOCATION_STANDARD。对于其他一些键,它们的值可以在两个地方出现,这些键定义如下:

  • “Shift”, “Control”, “Alt”, “Meta"的location可以是DOM_KEY_LOCATION_LEFT, DOM_KEY_LOCATION_RIGHT
  • “ArrowDown”, “ArrowLeft”, “ArrowRight”, “ArrowUp"的location可以是DOM_KEY_LOCATION_STANDARD, DOM_KEY_LOCATION_NUMPAD
  • “End”, “Home”, “PageDown”, “PageUp"的location可以是DOM_KEY_LOCATION_STANDARD, DOM_KEY_LOCATION_NUMPAD
  • “0”, “1”, “2”, “2”, “4”, “5”, “6”, “7”, “8”, “9”, “.”, “Enter”, “+”, “-”, “*”, “/“的location可以是DOM_KEY_LOCATION_STANDARD, DOM_KEY_LOCATION_NUMPAD

可以看到,UIEvents试图将具体键所在的位置暴露给上层的应用程序。

键盘事件类型只有两种:

  • keydown
  • keyup

敲击一个按键输入的时候,事件系列如下:

  • keydown
  • beforeinput (只有能够产生字符的键才有此事件)
  • input(只有字符被插入DOM时才产生这个事件)
  • keyup

如果按住一个按键,会持续产生以下事件序列:

  1. keydown
  2. beforeinput(只有能够产生字符的键才有此事件)
  3. input(只有字符被插入DOM时才产生这个事件)

字符合成事件(Composition Events)

有一些字符不在键盘默认可以产生的字符集合之中,针对这种情况,操作系统需要使用一些辅助措施,比如使用键盘映射,或者输入法来解决这个问题。键盘映射的例子,macos下按ALT+P可以产生一个π字符;对于输入法,大家都很熟悉了,中文就是使用输入法输入的。

字符合成事件的定义:

[Constructor(DOMString type, optional CompositionEventInit eventInitDict), Exposed=Window]
interface CompositionEvent : UIEvent {
  readonly attribute DOMString data;
};

使用输入法合成事件的时候,通常会产生以下事件:

  • compositionstart表示开始合成
  • compositionupdate表示合成过程中的更新
  • compositionend表示此次合成结束,也就是按了回车,字符输入

字符合成事件不止可以用于输入法,也可以用于手写输入设备,下面是一个例子

  1. compositionstart,开始识别,数据为空
  2. compositionupdate,产生候选列表,最佳匹配“test”,数据为“test”
  3. compositionupdate,用户不选择最佳匹配,而选择了“text”,数据为“text”
  4. compositionend,识别结束,数据为“text”

compositionstart是在用户敲击键盘的时候产生的,所以在compositionstart之前会先产生一个keydown事件。如果这个keydown事件被取消,那么后续的合成事件不会派发。另外一种情况是,如果compositionstart事件本身被中止,那么应该立马产生一个compositionend事件来中止事件合成过程。

字符合成过程是和键盘事件交织在一起的:

  1. keydown
  2. compositionstart(进入合成状态)
  3. compositionupdate
  4. keyup
  5. ……
  6. keydown
  7. compositionend((退出合成状态)
  8. keyup

字符合成过程也是和输入事件交织子啊一起的:

  1. beforeinput
  2. compositionupdate
  3. (DOM更新)
  4. input
  5. compositionend

键盘事件和虚拟码

5. Keyboard events and key values

当键盘上的一个键其实蕴含了很多信息:

  • 机械相关的信息:按键的尺寸、位置
  • 按键的直观标识:比如H键上的H就是个标识,但是按下H键一定会产生H字符吗?
  • 按键生成的键码:按键产生的虚拟码,按下H键所产生的H字符

按下一个键,然后最后产生的字符的过程有如此大的不确定性。一个浏览器不可能要求所有的键盘长什么样,有什么样的布局,所以UIEvents通过下面两个文档描绘了一个键盘应该是什么样的,支持什么键;剩下的就交给浏览器和操作系统去处理了:

为了区分一个按键的输出属性和物理属性,一个按键会产生两种值,分别是:Key和Code。Key代表的是一个键按下的输出,而Code代表的是布局相关的物理属性,下面是例子:

  • US键盘按下”'“之后,产生key是”'",code是"Quote”
  • Japanese按下”:“之后,产生key是”:",code是"Quote”
  • US Intl按下"Dead"之后,产生的key是"Dead”,code"Quote"

code值可以看成具体的物理键盘布局到一个理想键盘布局的映射,这样可以提供一层抽象,避免应用程序去处理具体的键盘布局。

keycode.info是一个网页,可以显示Javascript的击键信息。

其他参考

(完)