此文是W3C UI Events标准的阅读笔记。UI Events是一些列预定好的DOM事件,主要用来跟用户交互。
UI Events,后称UI事件体系,定义了一套用于用户交互的UI事件,以及该系列事件如何与DOM树交互。同时,UI事件体系还定义了了触发它们的图形控件们,以便不同的浏览器都实现一套具有相同事件属性的控件。
3. DOM事件架构
3.1章节描述了事件的派发机制,有一个非常直观的图。应用可以通过dispatchEvent
派发一个事件。根据图形系统的工作机制,交互事件(鼠标、键盘)一般是先由窗口捕获,然后再通过宿主语言(HTML、XML、SVG等等)的DOM结构向后继节点派发,知道到达目标节点只会再反弹。这个传播的过程一共有三个阶段:前往目标节点途中(capture phase)、到达目标节点(target phase)、从目标节点返回(bubble phase)。事件对象带有propagation path
属性,会记录其传播路径(从顶层节点到目标节点)。事件的传播是可控制的。事件可以被途中的某个节点截获,从而停止传播;也可以一开始就设置禁止事件的返回阶段。
事件可以有副作用。比如一个点击事件到达一个表单按键之后,默认会提交这个表单。默认的副作用可以被preventDefault()
避免,避免之后defaultPrevented
会返回true。具有这种特性的事件称为一个可撤销事件,其cancelable
属性返回true。如果事件是通过dispatchEvent
派发的,那么被撤销的事件会导致此函数返回false。
有一些事件的受众是共享资源,比如那些修改DOM树的事件。这些事件就需要进行协调,而协调是采用一种同步的机制。这些事件会被排在一个队列中,依次发送作用,这些事件称为同步事件。另外一些事件产生的效果互不影响,这些事件可以同时进行,这些事件称为异步事件。
事件可以有不同的来源,对于用户代理(User Agent,也就是浏览器)自己产生的事件比外部产生的事可信度要高。这些事件的isTrusted
会返回true。其他对于createEvent()
、initEvent()
、dispatchEvent()
等方法产生的事件,其isTrusted
返回false。可信事件对可以修改的资源范围大,权限高;而非可信事件则相反,通常没有默认动作,就像是preventDefault()
被调用了的感觉。
一个反例是click事件,即便不可信,也会触发默认动作。
一些事件对象带有默认的事件激发行为( activation behavior )。比如当一个click事件作用于一个<a>
元素,会激发其默认效果,也就是打开一个链接。基于事件的激发器大概有几种控制模式,定时控制、条件控制以及状态控制。
对于键盘事件和鼠标事件,它们的类型KeyboardEvent和MouseEvent在构造的时候可以接收额外的参数EventModifierInit
,主要用来表示在击键的时候,是否按下了修饰按键(比如CTRL、ALT、SHIFT等等)。随后可以通过getModifierState()
来获取修饰按键的状态。
dictionary EventModifierInit : UIEventInit {
boolean ctrlKey = false;
boolean shiftKey = false;
boolean altKey = false;
boolean metaKey = false;
boolean modifierAltGraph = false;
boolean modifierCapsLock = false;
boolean modifierFn = false;
boolean modifierFnLock = false;
boolean modifierHyper = false;
boolean modifierNumLock = false;
boolean modifierScrollLock = false;
boolean modifierSuper = false;
boolean modifierSymbol = false;
boolean modifierSymbolLock = false;
};
事件类型
DOM支持多种事件组(Event Module)。UIEvents定义了下层设备相关的事件组,以及用于修改DOM文档的事件组。
用户界面事件组(UI Event Types)
用户界面事件的类型定义如下:
[Constructor(DOMString type, optional UIEventInit eventInitDict), Exposed=Window]
interface UIEvent : Event {
readonly attribute Window? view;
readonly attribute long detail;
};
事件罗列(值得反复参考):
- load(资源加载成功时派发)
- unload(资源卸载时派发)
- abort(资源加载失败)
- error(无法解析加载的资源)
- select(当用户选中一些文字)
有趣的是load是异步事件,而unload以及abort是同步事件。
输入焦点事件组(Focus Events)
事件定义如下:
[Constructor(DOMString type, optional FocusEventInit eventInitDict), Exposed=Window]
interface FocusEvent : UIEvent {
readonly attribute EventTarget? relatedTarget;
};
焦点事件有时候会涉及到两个事件对象。比如焦点从一个输入框跳到另一个输入框的时候,这两个输入框都是相关的事件对象。relatedTarget
参数用来添加第二事件对象。
焦点是操作系统提供的服务,用于指示当前接收键盘事件的对象。本规范中只定义的焦点事件范围仅限于浏览器的DOM的document之内。document可以有一至多个focus ring,用来把多个能接收焦点的子元素组织在一起。可以用TAB来在一个focus ring中切换焦点。不是所有的HTML元素都能够接收焦点。对于某个能够接收焦点的HTML元素,也不是所有状态下都能够接收焦点。
焦点事件类型:
- blur
- focus
- focusin
- focusout
这几个事件都是同步的
下面是无焦点 =》焦点已到目标一 =》 焦点移到目标二过程中产生的事件:
- focusin (目标一快要接收焦点)
- focus (目标一接收焦点)
- focusout(目标一快要丢失焦点)
- focusin(目标二快要接收焦点)
- blur(目标一丢失焦点)
- focus(目标二接收焦点)
(本篇完)