[TOC]
十、事件种类
1. 鼠标事件
鼠标事件指与鼠标相关的事件,继承了MouseEvent
接口。具体的事件主要有以下一些。
click
:按下鼠标(通常是按下主按钮)时触发。chrome浏览器右键、滚轮不会触发 dblclick
:在同一个元素上双击鼠标时触发。 mousedown
:按下鼠标键时触发。 mouseup
:释放按下的鼠标键时触发。 mousemove
:当鼠标在一个节点内部移动时触发。当鼠标持续移动时,该事件会连续触发。为了避免性能问题,建议对该事件的监听函数做一些限定,比如限定一段时间内只能运行一次。 mouseenter
:鼠标进入一个节点时触发,进入子节点不会触发这个事件(详见后文)。 mouseover
:鼠标进入一个节点时触发,进入子节点会再一次触发这个事件(详见后文)。 mouseout
:鼠标离开一个节点时触发,离开父节点也会触发这个事件(详见后文)。 mouseleave
:鼠标离开一个节点时触发,离开父节点不会触发这个事件(详见后文)。 contextmenu
:按下鼠标右键时(上下文菜单出现前)触发,或者按下“上下文菜单键”时触发。 wheel
:滚动鼠标的滚轮时触发,该事件继承的是WheelEvent
接口。
click
事件指的是,用户在同一个位置先完成mousedown
动作,再完成mouseup
动作。因此,触发顺序是,mousedown
首先触发,mouseup
接着触发,click
最后触发。
dblclick
事件则会在mousedown
、mouseup
、click
之后触发。
mouseover
事件和mouseenter
事件,都是鼠标进入一个节点时触发。两者的区别是,mouseenter
事件只触发一次,而只要鼠标在节点内部移动,mouseover
事件会在子节点上触发多次。
上面代码中,在父节点内部进入子节点,不会触发mouseenter
事件,但是会触发mouseover
事件。
mouseout
事件和mouseleave
事件,都是鼠标离开一个节点时触发。两者的区别是,在父元素内部离开一个子元素时,mouseleave
事件不会触发,而mouseout
事件会触发。
上面代码中,在父节点内部离开子节点,不会触发mouseleave
事件,但是会触发mouseout
事件。
2. MouseEvent 接口概述
MouseEvent
接口代表了鼠标相关的事件,单击(click)、双击(dblclick)、松开鼠标键(mouseup)、按下鼠标键(mousedown)等动作,所产生的事件对象都是MouseEvent
实例。此外,滚轮事件和拖拉事件也是MouseEvent
实例。
MouseEvent
接口继承了Event
接口,所以拥有Event
的所有属性和方法。它还有自己的属性和方法。
浏览器原生提供一个MouseEvent
构造函数,用于新建一个MouseEvent
实例。
MouseEvent
构造函数接受两个参数。第一个参数是字符串,表示事件名称;第二个参数是一个事件配置对象,该参数可选。除了Event
接口的实例配置属性,该对象可以配置以下属性,所有属性都是可选的。
screenX
:数值,鼠标相对于屏幕的水平位置(单位像素),默认值为0,设置该属性不会移动鼠标。 screenY
:数值,鼠标相对于屏幕的垂直位置(单位像素),其他与screenX
相同。 clientX
:数值,鼠标相对于程序窗口的水平位置(单位像素),默认值为0,设置该属性不会移动鼠标。 clientY
:数值,鼠标相对于程序窗口的垂直位置(单位像素),其他与clientX
相同。 ctrlKey
:布尔值,是否同时按下了 Ctrl 键,默认值为false
。 shiftKey
:布尔值,是否同时按下了 Shift 键,默认值为false
。 altKey
:布尔值,是否同时按下 Alt 键,默认值为false
。 metaKey
:布尔值,是否同时按下 Meta 键,默认值为false
。 button
:数值,表示按下了哪一个鼠标按键,默认值为0
,表示按下主键(通常是鼠标的左键)或者当前事件没有定义这个属性;1
表示按下辅助键(通常是鼠标的中间键),2
表示按下次要键(通常是鼠标的右键)。 buttons
:数值,表示按下了鼠标的哪些键,是一个三个比特位的二进制值,默认为0
(没有按下任何键)。1
(二进制001
)表示按下主键(通常是左键),2
(二进制010
)表示按下次要键(通常是右键),4
(二进制100
)表示按下辅助键(通常是中间键)。因此,如果返回3
(二进制011
)就表示同时按下了左键和右键。 relatedTarget
:节点对象,表示事件的相关节点,默认为null
。mouseenter
和mouseover
事件时,表示鼠标刚刚离开的那个元素节点;mouseout
和mouseleave
事件时,表示鼠标正在进入的那个元素节点。
上面代码生成一个鼠标点击事件,并触发该事件。
3. MouseEvent 接口的实例属性
MouseEvent.altKey
、MouseEvent.ctrlKey
、MouseEvent.metaKey
、MouseEvent.shiftKey
这四个属性都返回一个布尔值,表示事件发生时,是否按下对应的键。它们都是只读属性。
altKey
属性:Alt 键 ctrlKey
属性:Ctrl 键 metaKey
属性:Meta 键(Mac 键盘是一个四瓣的小花,Windows 键盘是 Windows 键) shiftKey
属性:Shift 键
上面的代码中, 鼠标点击按钮会输出是否同时按下对应的键。
MouseEvent.button
属性返回一个数值,表示事件发生时按下了鼠标的哪个键。该属性只读。
0:按下主键(通常是左键),或者该事件没有初始化这个属性(比如mousemove
事件)。
1:按下辅助键(通常是中键或者滚轮键)。
2:按下次键(通常是右键)。
MouseEvent.buttons
属性返回一个三个比特位的值,表示同时按下了哪些键。它用来处理同时按下多个鼠标键的情况。该属性只读。
1:二进制为001
(十进制的1),表示按下左键。
2:二进制为010
(十进制的2),表示按下右键。
4:二进制为100
(十进制的4),表示按下中键或滚轮键。
同时按下多个键的时候,每个按下的键对应的比特位都会有值。比如,同时按下左键和右键,会返回3(二进制为011)。
上面代码测试鼠标的按键。
3.3 MouseEvent.clientX,MouseEvent.clientY
MouseEvent.clientX
属性返回鼠标位置相对于浏览器窗口左上角的水平坐标(单位像素) MouseEvent.clientY
属性返回垂直坐标。这两个属性都是只读属性
这两个属性还分别有一个别名MouseEvent.x
和MouseEvent.y
3.4 MouseEvent.movementX,MouseEvent.movementY
MouseEvent.movementX
属性返回当前位置与上一个mousemove
事件之间的水平距离(单位像素),只读 MouseEvent.movementY
属性返回当前位置与上一个mousemove
事件之间的垂直距离(单位像素),只读
数值上他们等于下面的计算公式:
上面的代码中,鼠标在按钮上移动的时候可以发现值的变化。
3.5 MouseEvent.screenX,MouseEvent.screenY
MouseEvent.screenX
属性返回鼠标位置相对于屏幕左上角的水平坐标(单位像素),只读 MouseEvent.screenY
属性返回垂直坐标,只读属性
3.6 MouseEvent.offsetX,MouseEvent.offsetY
MouseEvent.offsetX
属性返回鼠标位置与目标节点左侧的padding
边缘的水平距离(单位像素),只读 MouseEvent.offsetY
属性返回与目标节点上方的padding
边缘的垂直距离,只读
上面代码中,鼠标如果在p
元素的中心位置点击,会返回150 150
。因此中心位置距离左侧和上方的padding
边缘,等于padding
的宽度(100像素)加上元素内容区域一半的宽度(50像素)。
3.7 MouseEvent.pageX,MouseEvent.pageY
MouseEvent.pageX
属性返回鼠标位置与文档左侧边缘的距离(单位像素),只读 MouseEvent.pageY
属性返回与文档上侧边缘的距离(单位像素),只读
它们的返回值都包括文档不可见的部分。
上面代码中,页面高度为2000像素,会产生垂直滚动条。滚动到页面底部,点击鼠标输出的pageY
值会接近2000。
MouseEvent.relatedTarget
属性返回事件的相关节点。对于那些没有相关节点的事件,该属性返回null
。该属性只读。
下表列出不同事件的target
属性值和relatedTarget
属性值义。
事件名称 | target 属性 | relatedTarget 属性 |
focusin | 接受焦点的节点 | 丧失焦点的节点 |
focusout | 丧失焦点的节点 | 接受焦点的节点 |
mouseenter | 将要进入的节点 | 将要离开的节点 |
mouseleave | 将要离开的节点 | 将要进入的节点 |
mouseout | 将要离开的节点 | 将要进入的节点 |
mouseover | 将要进入的节点 | 将要离开的节点 |
dragenter | 将要进入的节点 | 将要离开的节点 |
dragexit | 将要离开的节点 | 将要进入的节点 |
4. MouseEvent 接口的实例方法
4.1 MouseEvent.getModifierState()
MouseEvent.getModifierState
方法返回一个布尔值,表示有没有按下特定的功能键。它的参数是一个表示功能键的字符串。
上面的代码可以了解用户是否按下了大写键。
5. WheelEvent 接口
WheelEvent 接口继承了 MouseEvent 实例,代表鼠标滚轮事件的实例对象。目前,鼠标滚轮相关的事件只有一个wheel
事件,用户滚动鼠标的滚轮,就生成这个事件的实例。
浏览器原生提供WheelEvent()
构造函数,用来生成WheelEvent
实例。
WheelEvent()
构造函数可以接受两个参数,第一个是字符串,表示事件类型,对于滚轮事件来说,这个值目前只能是wheel
。第二个参数是事件的配置对象。该对象的属性除了Event
、UIEvent
的配置属性以外,还可以接受以下几个属性,所有属性都是可选的。
deltaX
:数值,表示滚轮的水平滚动量,默认值是 0.0。 deltaY
:数值,表示滚轮的垂直滚动量,默认值是 0.0。 deltaZ
:数值,表示滚轮的 Z 轴滚动量,默认值是 0.0。 deltaMode
:数值,表示相关的滚动事件的单位,适用于上面三个属性。0
表示滚动单位为像素,1
表示单位为行,2
表示单位为页,默认为0
。
5.1 实例属性
WheelEvent
事件实例除了具有Event
和MouseEvent
的实例属性和实例方法,还有一些自己的实例属性,但是没有自己的实例方法。
下面的属性都是只读属性
WheelEvent.deltaX
:数值,表示滚轮的水平滚动量。
WheelEvent.deltaY
:数值,表示滚轮的垂直滚动量。
WheelEvent.deltaZ
:数值,表示滚轮的 Z 轴滚动量。
WheelEvent.deltaMode
:数值,表示上面三个属性的单位,0
是像素,1
是行,2
是页。
6. 键盘事件
键盘事件由用户击打键盘触发,主要有keydown
、keypress
、keyup
三个事件,它们都继承了KeyboardEvent
接口。
keydown
:按下键盘时触发。 keypress
:按下有值的键时触发,即按下 Ctrl、Alt、Shift、Meta 这样无值的键,这个事件不会触发。对于有值的键,按下时先触发keydown
事件,再触发这个事件。 keyup
:松开键盘时触发该事件。
如果用户一直按键不松开,就会连续触发键盘事件,触发的顺序如下。
- keydown
- keypress
- keydown
- keypress
- …(重复以上过程)
- keyup
上面的代码中,在输入框中输入一个字母的时候输出:keydown
、keypress
、keyup
在输入框按下shift键的时候输出:keydown
、keyup
7. KeyboardEvent 接口
KeyboardEvent
接口用来描述用户与键盘的互动。这个接口继承了Event
接口,并且定义了自己的实例属性和实例方法。
浏览器原生提供KeyboardEvent
构造函数,用来新建键盘事件的实例。
KeyboardEvent
构造函数接受两个参数。第一个参数是字符串,表示事件类型;第二个参数是一个事件配置对象,该参数可选。除了Event
接口提供的属性,还可以配置以下字段,它们都是可选。
key
:字符串,当前按下的键,默认为空字符串。 code
:字符串,表示当前按下的键的字符串形式,默认为空字符串。 location
:整数,当前按下的键的位置,默认为0
。 ctrlKey
:布尔值,是否按下 Ctrl 键,默认为false
。 shiftKey
:布尔值,是否按下 Shift 键,默认为false
。 altKey
:布尔值,是否按下 Alt 键,默认为false
。 metaKey
:布尔值,是否按下 Meta 键,默认为false
。 repeat
:布尔值,是否重复按键,默认为false
。
8. KeyboardEvent 的实例属性
以下属性都是只读属性,返回一个布尔值,表示是否按下对应的键。
KeyboardEvent.altKey
:是否按下 Alt 键 KeyboardEvent.ctrlKey
:是否按下 Ctrl 键 KeyboardEvent.metaKey
:是否按下 meta 键(Mac 系统是一个四瓣的小花,Windows 系统是 windows 键) KeyboardEvent.shiftKey
:是否按下 Shift 键
8.2 KeyboardEvent.code
KeyboardEvent.code
属性返回一个字符串,表示当前按下的键的字符串形式。该属性只读。
下面是一些常用键的字符串形式,其他键请查文档。
数字键0 - 9:返回digital0
- digital9
字母键A - z:返回KeyA
- KeyZ
功能键F1 - F12:返回 F1
- F12
方向键:返回ArrowDown
、ArrowUp
、ArrowLeft
、ArrowRight
Alt 键:返回AltLeft
或AltRight
Shift 键:返回ShiftLeft
或ShiftRight
Ctrl 键:返回ControLeft
或ControlRight
上面的代码执行后,在页面上按键盘后,会输出对应按键的code
8.3 KeyboardEvent.key
KeyboardEvent.key
属性返回一个字符串,表示按下的键名。该属性只读。
如果按下的键代表可打印字符,则返回这个字符,比如数字、字母。
如果按下的键代表不可打印的特殊字符,则返回预定义的键值,比如 Backspace,Tab,Enter,Shift,Control,Alt,CapsLock,Esc,Spacebar,PageUp,PageDown,End,Home,Left,Right,Up,Down,PrintScreen,Insert,Del,Win,F1~F12,NumLock,Scroll 等。
如果同时按下一个控制键和一个符号键,则返回符号键的键名。比如,按下 Ctrl + a,则返回a
;按下 Shift + a,则返回大写的A
。
如果无法识别键名,返回字符串Unidentified
。
8.4 KeyboardEvent.location
上面的代码可以监控到按键在键盘的位置。
8.5 KeyboardEvent.repeat
KeyboardEvent.repeat
返回一个布尔值,代表该键是否被按着不放,以便判断是否重复这个键,即浏览器会持续触发keydown
和keypress
事件,直到用户松开手为止。
上面的代码执行后,在页面上按住一个键不放就出测试出repeat,
注意监听keyup
不会触发repeat
。
9. KeyboardEvent 的实例方法
9.1 KeyboardEvent.getModifierState()
KeyboardEvent.getModifierState()
方法返回一个布尔值,表示是否按下或激活指定的功能键。
它的常用参数如下:
Alt
:Alt 键 CapsLock
:大写锁定键 Control
:Ctrl 键 Meta
:Meta 键 NumLock
:数字键盘开关键 Shift
:Shift 键
10. 进度事件
进度事件用来描述资源加载的进度,主要由 AJAX 请求、<img>
、<audio>
、<video>
、<style>
、<link>
等外部资源的加载触发,继承了ProgressEvent
接口。它主要包含以下几种事件:
abort
:外部资源中止加载时(比如用户取消)触发。如果发生错误导致中止,不会触发该事件。 error
:由于错误导致外部资源无法加载时触发。 load
:外部资源加载成功时触发。 loadstart
:外部资源开始加载时触发。 loadend
:外部资源停止加载时触发,发生顺序排在error
、abort
、load
等事件的后面。 progress
:外部资源加载过程中不断触发。 timeout
:加载超时时触发。
注意,除了资源下载,文件上传也存在这些事件。
上面代码在图片元素加载完成后,为图片元素添加一个finished
的 Class。如果加载失败,就把图片元素的样式设置为不显示。
有时候,图片加载会在脚本运行之前就完成,尤其是当脚本放置在网页底部的时候,因此有可能load
和error
事件的监听函数根本不会执行。所以,比较可靠的方式,是用complete
属性先判断一下是否加载完成。
由于 DOM 的元素节点没有提供是否加载错误的属性,所以error
事件的监听函数最好放在<img>
元素的 HTML 代码中,这样才能保证发生加载错误时百分之百会执行。
loadend
事件的监听函数,可以用来取代abort
事件、load
事件、error
事件的监听函数,因为它总是在这些事件之后发生。
loadend
事件本身不提供关于进度结束的原因,但可以用它来做所有加载结束场景都需要做的一些操作。
另外,error
事件有一个特殊的性质,就是不会冒泡。所以,子元素的error
事件,不会触发父元素的error
事件监听函数。
11. ProgressEvent 接口
ProgressEvent
接口主要用来描述外部资源加载的进度,比如 AJAX 加载、<img>
、<video>
、<style>
、<link>
等外部资源加载。进度相关的事件都继承了这个接口。
浏览器原生提供了ProgressEvent()
构造函数,用来生成事件实例。
ProgressEvent()
构造函数接受两个参数。第一个参数是字符串,表示事件的类型,这个参数是必须的。第二个参数是一个配置对象,表示事件的属性,该参数可选。配置对象除了可以使用Event
接口的配置属性,还可以使用下面的属性,所有这些属性都是可选的。
lengthComputable
:布尔值,表示加载的总量是否可以计算,默认是false
。 loaded
:整数,表示已经加载的量,默认是0
。 total
:整数,表示需要加载的总量,默认是0
。
ProgressEvent
具有对应的实例属性。
ProgressEvent.lengthComputable
ProgressEvent.loaded
ProgressEvent.total
如果ProgressEvent.lengthComputable
为false
,ProgressEvent.total
实际上是没有意义的。
下面是一个例子。
上面代码先构造一个load
事件,抛出后被监听函数捕捉到。
下面是一个实际的例子。
上面是下载过程的进度事件,还存在上传过程的进度事件。这时所有监听函数都要放在XMLHttpRequest.upload
对象上面。
12. 拖拉事件
拖拉(drag)指的是,用户在某个对象上按下鼠标键不放,拖动它到另一个位置,然后释放鼠标键,将该对象放在那里。
拖拉的对象有好几种,包括元素节点、图片、链接、选中的文字等等。在网页中,除了元素节点默认不可以拖拉,其他(图片、链接、选中的文字)都是可以直接拖拉的。为了让元素节点可拖拉,可以将该节点的draggable
属性设为true
。
draggable
属性可用于任何元素节点,但是图片(<img>
)和链接(<a>
)不加这个属性,就可以拖拉。对于它们,用到这个属性的时候,往往是将其设为false
,防止拖拉这两种元素。
注意,一旦某个元素节点的draggable
属性设为true
,就无法再用鼠标选中该节点内部的文字或子节点了。
当元素节点或选中的文本被拖拉时,就会持续触发拖拉事件,包括以下一些事件。
drag
:拖拉过程中,在被拖拉的节点上持续触发(相隔几百毫秒)。 dragstart
:用户开始拖拉时,在被拖拉的节点上触发,该事件的target
属性是被拖拉的节点。通常应该在这个事件的监听函数中,指定拖拉的数据。 dragend
:拖拉结束时(释放鼠标键或按下 ESC 键)在被拖拉的节点上触发,该事件的target
属性是被拖拉的节点。它与dragstart
事件,在同一个节点上触发。不管拖拉是否跨窗口,或者中途被取消,dragend
事件总是会触发的。 dragenter
:拖拉进入当前节点时,在当前节点上触发一次,该事件的target
属性是当前节点。通常应该在这个事件的监听函数中,指定是否允许在当前节点放下(drop)拖拉的数据。如果当前节点没有该事件的监听函数,或者监听函数不执行任何操作,就意味着不允许在当前节点放下数据。在视觉上显示拖拉进入当前节点,也是在这个事件的监听函数中设置。 dragover
:拖拉到当前节点上方时,在当前节点上持续触发(相隔几百毫秒),该事件的target
属性是当前节点。该事件与dragenter
事件的区别是,dragenter
事件在进入该节点时触发,然后只要没有离开这个节点,dragover
事件会持续触发。 dragleave
:拖拉操作离开当前节点范围时,在当前节点上触发,该事件的target
属性是当前节点。如果要在视觉上显示拖拉离开操作当前节点,就在这个事件的监听函数中设置。 drop
:被拖拉的节点或选中的文本,释放到目标节点时,在目标节点上触发。注意,如果当前节点不允许drop
,即使在该节点上方松开鼠标键,也不会触发该事件。如果用户按下 ESC 键,取消这个操作,也不会触发该事件。该事件的监听函数负责取出拖拉数据,并进行相关处理。
下面的例子展示,如何动态改变被拖动节点的背景色。
上面代码中,div
节点被拖动时,背景色会变为红色,拖动结束,又变回绿色。
下面是一个例子,展示如何实现将一个节点从当前父节点,拖拉到另一个父节点中。
关于拖拉事件,有以下几个注意点:
- 拖拉过程只触发以上这些拖拉事件,尽管鼠标在移动,但是鼠标事件不会触发。
- 将文件从操作系统拖拉进浏览器,不会触发
dragstart
和dragend
事件。 dragenter
和dragover
事件的监听函数,用来取出拖拉的数据(即允许放下被拖拉的元素)。由于网页的大部分区域不适合作为放下拖拉元素的目标节点,所以这两个事件的默认设置为当前节点不允许接受被拖拉的元素。如果想要在目标节点上放下的数据,首先必须阻止这两个事件的默认行为。
上面代码中,如果不取消拖拉事件或者阻止默认行为,就不能在div
节点上放下被拖拉的节点。
13. DragEvent 接口
拖拉事件都继承了DragEvent
接口,这个接口又继承了MouseEvent
接口和Event
接口。
浏览器原生提供一个DragEvent()
构造函数,用来生成拖拉事件的实例对象。
DragEvent()
构造函数接受两个参数,第一个参数是字符串,表示事件的类型,该参数必须;第二个参数是事件的配置对象,用来设置事件的属性,该参数可选。配置对象除了接受MouseEvent
接口和Event
接口的配置属性,还可以设置dataTransfer
属性要么是null
,要么是一个DataTransfer
接口的实例。
DataTransfer
的实例对象用来读写拖拉事件中传输的数据
14. DataTransfer 接口概述
所有拖拉事件的实例都有一个DragEvent.dataTransfer
属性,用来读写需要传递的数据。这个属性的值是一个DataTransfer
接口的实例。
浏览器原生提供一个DataTransfer()
构造函数,用来生成DataTransfer
实例对象。
DataTransfer()
构造函数不接受参数。
拖拉的数据分成两方面:数据的种类(又称格式)和数据的值。数据的种类是一个 MIME 字符串(比如text/plain
、image/jpeg
),数据的值是一个字符串。一般来说,如果拖拉一段文本,则数据默认就是那段文本;如果拖拉一个链接,则数据默认就是链接的 URL。
拖拉事件开始时,开发者可以提供数据类型和数据值。拖拉过程中,开发者通过dragenter
和dragover
事件的监听函数,检查数据类型,以确定是否允许放下(drop)被拖拉的对象。比如,在只允许放下链接的区域,检查拖拉的数据类型是否为text/uri-list
。
发生drop
事件时,监听函数取出拖拉的数据,对其进行处理。
15.DataTransfer 的实例属性
15.1 DataTransfer.dropEffect
DataTransfer.dropEffect
属性用来设置放下(drop)被拖拉节点时的效果,会影响到拖拉经过相关区域时鼠标的形状。它可能取下面的值。
- copy:复制被拖拉的节点
- move:移动被拖拉的节点
- link:创建指向被拖拉的节点的链接
- none:无法放下被拖拉的节点
除了上面这些值,设置其他的值都是无效的。
上面代码中,被拖拉元素一旦drop
,接受的区域会复制该节点。
dropEffect
属性一般在dragenter
和dragover
事件的监听函数中设置,对于dragstart
、drag
、dragleave
这三个事件,该属性不起作用。因为该属性只对接受被拖拉的节点的区域有效,对被拖拉的节点本身是无效的。进入目标区域后,拖拉行为会初始化成设定的效果。
15.2 DataTransfer.effectAllowed
DataTransfer.effectAllowed
属性设置本次拖拉中允许的效果。它可能取下面的值。
- copy:复制被拖拉的节点
- move:移动被拖拉的节点
- link:创建指向被拖拉节点的链接
- copyLink:允许
copy
或link
- copyMove:允许
copy
或move
- linkMove:允许
link
或move
- all:允许所有效果
- none:无法放下被拖拉的节点
- uninitialized:默认值,等同于
all
如果某种效果是不允许的,用户就无法在目标节点中达成这种效果。
这个属性与dropEffect
属性是同一件事的两个方面。前者设置被拖拉的节点允许的效果,后者设置接受拖拉的区域的效果,它们往往配合使用。
dragstart
事件的监听函数,可以用来设置这个属性。其他事件的监听函数里面设置这个属性是无效的。
只要dropEffect
属性和effectAllowed
属性之中,有一个为none
,就无法在目标节点上完成drop
操作。
15.3 DataTransfer.files
DataTransfer.files
属性是一个 FileList 对象,包含一组本地文件,可以用来在拖拉操作中传送。如果本次拖拉不涉及文件,则该属性为空的 FileList 对象。
下面就是一个接收拖拉文件的例子。
上面代码中,通过dataTransfer.files
属性读取被拖拉的文件的信息。如果想要读取文件内容,就要使用FileReader
对象。
15.4 DataTransfer.types
DataTransfer.types
属性是一个只读的数组,每个成员是一个字符串,里面是拖拉的数据格式(通常是 MIME 值)。比如,如果拖拉的是文字,对应的成员就是text/plain
。
下面是一个例子,通过检查dataTransfer
属性的类型,决定是否允许在当前节点执行drop
操作。
上面代码中,只有当被拖拉的节点是一个链接时,才允许在当前节点放下。
15.5 DataTransfer.items
DataTransfer.items
属性返回一个类似数组的只读对象(DataTransferItemList 实例),每个成员就是本次拖拉的一个对象(DataTransferItem 实例)。如果本次拖拉不包含对象,则返回一个空对象。
DataTransferItemList 实例具有以下的属性和方法。
length
:返回成员的数量 add(data, type)
:增加一个指定内容和类型(比如text/html
和text/plain
)的字符串作为成员 add(file)
:add
方法的另一种用法,增加一个文件作为成员 remove(index)
:移除指定位置的成员 clear()
:移除所有的成员
DataTransferItem 实例具有以下的属性和方法。
kind
:返回成员的种类(string
还是file
)。 type
:返回成员的类型(通常是 MIME 值)。 getAsFile()
:如果被拖拉是文件,返回该文件,否则返回null
。 getAsString(callback)
:如果被拖拉的是字符串,将该字符传入指定的回调函数处理。该方法是异步的,所以需要传入回调函数。
下面是一个例子。
上面的代码运行后,把文件拖进div中后,会在控制台显示信息。
16. DataTransfer 的实例方法
16.1 DataTransfer.setData()
DataTransfer.setData()
方法用来设置拖拉事件所带有的数据。该方法没有返回值。
上面代码为当前的拖拉事件加入纯文本数据。
该方法接受两个参数,都是字符串。第一个参数表示数据类型(比如text/plain
),第二个参数是具体数据。如果指定类型的数据在dataTransfer
属性不存在,那么这些数据将被加入,否则原有的数据将被新数据替换。
如果是拖拉文本框或者拖拉选中的文本,会默认将对应的文本数据,添加到dataTransfer
属性,不用手动指定。
上面代码中,拖拉这个<div>
元素会自动带上文本数据aaa
。
使用setData
方法,可以替换到原有数据。
上面代码中,拖拉数据实际上是bbb
,而不是aaa
。
下面是添加其他类型的数据。由于text/plain
是最普遍支持的格式,为了保证兼容性,建议最后总是保存一份纯文本格式的数据。
可以一次提供多种格式的数据。
上面代码中,通过在同一个事件上面,存放三种类型的数据,使得拖拉事件可以在不同的对象上面,drop
不同的值。注意,第一种格式是一个自定义格式,浏览器默认无法读取,这意味着,只有某个部署了特定代码的节点,才可能drop
(读取到)这个数据。
16.2 DataTransfer.getData()
DataTransfer.getData()
方法接受一个字符串(表示数据类型)作为参数,返回事件所带的指定类型的数据(通常是用setData
方法添加的数据)。如果指定类型的数据不存在,则返回空字符串。通常只有drop
事件触发后,才能取出数据。
下面是一个drop
事件的监听函数,用来取出指定类型的数据。
上面代码取出拖拉事件的文本数据,将其替换成当前节点的文本内容。注意,这时还必须取消浏览器的默认行为,因为假如用户拖拉的是一个链接,浏览器默认会在当前窗口打开这个链接。
getData
方法返回的是一个字符串,如果其中包含多项数据,就必须手动解析。
上面代码中,getData
方法返回的是一组链接,就必须自行解析。
类型值指定为URL
,可以取出第一个有效链接。
下面的例子是从多种类型的数据里面取出数据。
16.3 DataTransfer.clearData()
DataTransfer.clearData()
方法接受一个字符串(表示数据类型)作为参数,删除事件所带的指定类型的数据。如果没有指定类型,则删除所有数据。如果指定类型不存在,则调用该方法不会产生任何效果。
上面代码清除事件所带的text/uri-list
类型的数据。
该方法不会移除拖拉的文件,因此调用该方法后,DataTransfer.types
属性可能依然会返回Files
类型(前提是存在文件拖拉)。
注意,该方法只能在dragstart
事件的监听函数之中使用,因为这是拖拉操作的数据唯一可写的时机。
16.4 DataTransfer.setDragImage()
拖动过程中(dragstart
事件触发后),浏览器会显示一张图片跟随鼠标一起移动,表示被拖动的节点。这张图片是自动创造的,通常显示为被拖动节点的外观,不需要自己动手设置。
DataTransfer.setDragImage()
方法可以自定义这张图片。它接受三个参数。第一个是<img>
节点或者<canvas>
节点,如果省略或为null
,则使用被拖动的节点的外观;第二个和第三个参数为鼠标相对于该图片左上角的横坐标和右坐标。
下面是一个例子。
17. 触摸操作概述
浏览器的触摸 API 由三个部分组成。
- Touch:一个触摸点
- TouchList:多个触摸点的集合
- TouchEvent:触摸引发的事件实例
Touch
接口的实例对象用来触摸点(一根手指或者一根触摸笔),包括位置、大小、形状、压力、目标元素等属性。有时,触摸动作由多个触摸点(多根手指)组成,多个触摸点的集合由TouchList
接口的实例对象表示。TouchEvent
接口的实例对象代表由触摸引发的事件,只有触摸屏才会引发这一类事件。
很多时候,触摸事件和鼠标事件同时触发,即使这个时候并没有用到鼠标。这是为了让那些只定义鼠标事件、没有定义触摸事件的代码,在触摸屏的情况下仍然能用。如果想避免这种情况,可以用event.preventDefault
方法阻止发出鼠标事件。
18. Touch接口
18.1 Touch接口概述
Touch 接口代表单个触摸点。触摸点可能是一根手指,也可能是一根触摸笔。
浏览器原生提供Touch
构造函数,用来生成Touch
实例。
Touch
构造函数接受一个配置对象作为参数,它有以下属性。
identifier
:必需,类型为整数,表示触摸点的唯一 ID。 target
:必需,类型为元素节点,表示触摸点开始时所在的网页元素。 clientX
:可选,类型为数值,表示触摸点相对于浏览器窗口左上角的水平距离,默认为0。 clientY
:可选,类型为数值,表示触摸点相对于浏览器窗口左上角的垂直距离,默认为0。 screenX
:可选,类型为数值,表示触摸点相对于屏幕左上角的水平距离,默认为0。 screenY
:可选,类型为数值,表示触摸点相对于屏幕左上角的垂直距离,默认为0。 pageX
:可选,类型为数值,表示触摸点相对于网页左上角的水平位置(即包括页面的滚动距离),默认为0。 pageY
:可选,类型为数值,表示触摸点相对于网页左上角的垂直位置(即包括页面的滚动距离),默认为0。 radiusX
:可选,类型为数值,表示触摸点周围受到影响的椭圆范围的 X 轴半径,默认为0。 radiusY
:可选:类型为数值,表示触摸点周围受到影响的椭圆范围的 Y 轴半径,默认为0。 rotationAngle
:可选,类型为数值,表示触摸区域的椭圆的旋转角度,单位为度数,在0到90度之间,默认值为0。 force
:可选,类型为数值,范围在0
到1
之间,表示触摸压力。0
代表没有压力,1
代表硬件所能识别的最大压力,默认为0
。
18.2 Touch 接口的实例属性
(1)Touch.identifier
Touch.identifier
属性返回一个整数,表示触摸点的唯一 ID。这个值在整个触摸过程保持不变,直到触摸事件结束。
(2)Touch.screenX,Touch.screenY,Touch.clientX,Touch.clientY,pageX,pageY
Touch.screenX
属性和Touch.screenY
属性,分别表示触摸点相对于屏幕左上角的横坐标和纵坐标,与页面是否滚动无关。
Touch.clientX
属性和Touch.clientY
属性,分别表示触摸点相对于浏览器视口左上角的横坐标和纵坐标,与页面是否滚动无关。
Touch.pageX
属性和Touch.pageY
属性,分别表示触摸点相对于当前页面左上角的横坐标和纵坐标,包含了页面滚动带来的位移。
(3)Touch.radiusX,Touch.radiusY,Touch.rotationAngle
Touch.radiusX
属性和Touch.radiusY
属性,分别返回触摸点周围受到影响的椭圆范围的 X 轴半径和 Y 轴半径,单位为像素。乘以 2 就可以得到触摸范围的宽度和高度。
Touch.rotationAngle
属性表示触摸区域的椭圆的旋转角度,单位为度数,在0
到90
度之间。
上面这三个属性共同定义了用户与屏幕接触的区域,对于描述手指这一类非精确的触摸,很有帮助。指尖接触屏幕,触摸范围会形成一个椭圆,这三个属性就用来描述这个椭圆区域。
下面是一个示例。
(4)Touch.force
Touch.force
属性返回一个0
到1
之间的数值,表示触摸压力。0
代表没有压力,1
代表硬件所能识别的最大压力。
(5)Touch.target
Touch.target
属性返回一个元素节点,代表触摸发生时所在的那个元素节点。即使触摸点已经离开了这个节点,该属性依然不变。
上面的代码在Google的chrome浏览器中,打开开发者模式,设置为手机模式,点击一下屏幕就能看见输出。
19. TouchList 接口
TouchList
接口表示一组触摸点的集合。它的实例是一个类似数组的对象,成员是Touch
的实例对象,表示所有触摸点。用户用三根手指触摸,产生的TouchList
实例就会包含三个成员,每根手指的触摸点对应一个Touch
实例对象。
它的实例主要通过触摸事件的TouchEvent.touches
、TouchEvent.changedTouches
、TouchEvent.targetTouches
这几个属性获取。
它的实例属性和实例方法只有两个。
TouchList.length
:数值,表示成员数量(即触摸点的数量)。 TouchList.item()
:返回指定位置的成员,它的参数是该成员的位置编号(从零开始)。
上面的代码在chrome中开发者模式,手机模式,点击一下查看效果
20. TouchEvent 接口
20.1 概述
TouchEvent 接口继承了 Event 接口,表示由触摸引发的事件实例,通常来自触摸屏或轨迹板。除了被继承的属性以外,它还有一些自己的属性。
浏览器原生提供TouchEvent()
构造函数,用来生成触摸事件的实例。
TouchEvent()
构造函数可以接受两个参数,第一个参数是字符串,表示事件类型;第二个参数是事件的配置对象,该参数是可选的,对象的所有属性也是可选的。除了Event
接口的配置属性,该接口还有一些自己的配置属性。
touches
:TouchList
实例,代表所有的当前处于活跃状态的触摸点,默认值是一个空数组[]
。 targetTouches
:TouchList
实例,代表所有处在触摸的目标元素节点内部、且仍然处于活动状态的触摸点,默认值是一个空数组[]
。 changedTouches
:TouchList
实例,代表本次触摸事件的相关触摸点,默认值是一个空数组[]
。 ctrlKey
:布尔值,表示 Ctrl 键是否同时按下,默认值为false
。 shiftKey
:布尔值,表示 Shift 键是否同时按下,默认值为false
。 altKey
:布尔值,表示 Alt 键是否同时按下,默认值为false
。 metaKey
:布尔值,表示 Meta 键(或 Windows 键)是否同时按下,默认值为false
。
20.2 实例属性
TouchEvent 接口的实例具有Event
实例的所有属性和方法,此外还有一些它自己的实例属性,这些属性全部都是只读。
(1)TouchEvent.altKey,TouchEvent.ctrlKey,TouchEvent.shiftKey,TouchEvent.metaKey
TouchEvent.altKey
:布尔值,表示触摸时是否按下了 Alt 键。 TouchEvent.ctrlKey
:布尔值,表示触摸时是否按下了 Ctrl 键。 TouchEvent.shiftKey
:布尔值:表示触摸时是否按下了 Shift 键。 TouchEvent.metaKey
:布尔值,表示触摸时是否按下了 Meta 键(或 Windows 键)。
下面是一个示例
chrome开发者打开手机模式,点击一下即可查看效果。
(2)TouchEvent.changedTouches
TouchEvent.changedTouches
属性返回一个TouchList
实例,成员是一组Touch
实例对象,表示本次触摸事件的相关触摸点。
对于不同的时间,该属性的含义有所不同。
touchstart
事件:被激活的触摸点 touchmove
事件:发生变化的触摸点 touchend
事件:消失的触摸点(即不再被触碰的点)
下面是一个示例。
(3)TouchEvent.touches
TouchEvent.touches
属性返回一个TouchList
实例,成员是所有仍然处于活动状态(即触摸中)的触摸点。一般来说,一个手指就是一个触摸点。
下面是一个示例。
(4)TouchEvent.targetTouches
TouchEvent.targetTouches
属性返回一个TouchList
实例,成员是触摸事件的目标元素节点内部、所有仍然处于活动状态(即触摸中)的触摸点。
上面代码用来判断,是否所有触摸点都在目标元素内。
21. 触摸事件的种类
触摸引发的事件,有以下几种。可以通过TouchEvent.type
属性,查看到底发生的是哪一种事件。
touchstart
:用户开始触摸时触发,它的target
属性返回发生触摸的元素节点。 touchend
:用户不再接触触摸屏时(或者移出屏幕边缘时)触发,它的target
属性与touchstart
事件一致的,就是开始触摸时所在的元素节点。它的changedTouches
属性返回一个TouchList
实例,包含所有不再触摸的触摸点(即Touch
实例对象)。 touchmove
:用户移动触摸点时触发,它的target
属性与touchstart
事件一致。如果触摸的半径、角度、力度发生变化,也会触发该事件。 touchcancel
:触摸点取消时触发,比如在触摸区域跳出一个情态窗口(modal window)、触摸点离开了文档区域(进入浏览器菜单栏)、用户的触摸点太多,超过了支持的上限(自动取消早先的触摸点)。
下面是一个例子
22. 表单事件的种类
input
事件当<input>
、<select>
、<textarea>
的值发生变化时触发。对于复选框(<input type=checkbox>
)或单选框(<input type=radio>
),用户改变选项时,也会触发这个事件。另外,对于打开contenteditable
属性的元素,只要值发生变化,也会触发input
事件。
input
事件的一个特点,就是会连续触发,比如用户每按下一次按键,就会触发一次input
事件。
input
事件对象继承了InputEvent
接口。
上面的代码执行后,输入框中每次值的变化都会触发input事件。
22.2 select 事件
select
事件当在<input>
、<textarea>
里面选中文本时触发。
选中的文本可以通过event.target
元素的selectionDirection
、selectionEnd
、selectionStart
和value
属性拿到。
22.3 Change 事件
Change
事件当<input>
、<select>
、<textarea>
的值发生变化时触发。它与input
事件的最大不同,就是不会连续触发,只有当全部修改完成时才会触发,另一方面input
事件必然伴随change
事件。具体来说,分成以下几种情况。
- 激活单选框(radio)或复选框(checkbox)时触发。
- 用户提交时触发。比如,从下列列表(select)完成选择,在日期或文件输入框完成选择。
- 当文本框或
<textarea>
元素的值发生改变,并且丧失焦点时触发。
下面是一个例子。
22.4 invalid 事件
用户提交表单时,如果表单元素的值不满足校验条件,就会触发invalid
事件。
上面代码中,输入框是必填的。如果不填,用户点击按钮提交时,就会触发输入框的invalid
事件,导致提交被取消。
22.5 reset 事件,submit 事件
这两个事件发生在表单对象<form>
上,而不是发生在表单的成员上。
reset
事件当表单重置(所有表单成员变回默认值)时触发。
submit
事件当表单数据向服务器提交时触发。注意,submit
事件的发生对象是<form>
元素,而不是<button>
元素,因为提交的是表单,而不是按钮。
23. 资源事件
23.1 beforeunload 事件
beforeunload
事件在窗口、文档、各种资源将要卸载前触发。它可以用来防止用户不小心卸载资源。
如果该事件对象的returnValue
属性是一个非空字符串,那么浏览器就会弹出一个对话框,询问用户是否要卸载该资源。但是,用户指定的字符串可能无法显示,浏览器会展示预定义的字符串。如果用户点击“取消”按钮,资源就不会卸载。
上面代码中,用户如果关闭窗口,浏览器会弹出一个窗口,要求用户确认。
浏览器对这个事件的行为很不一致,有的浏览器调用event.preventDefault()
,也会弹出对话框。IE 浏览器需要显式返回一个非空的字符串,才会弹出对话框。而且,大多数浏览器在对话框中不显示指定文本,只显示默认文本。因此,可以采用下面的写法,取得最大的兼容性。
注意,许多手机浏览器默认忽略这个事件,桌面浏览器也有方法忽略这个事件。所以,它可能根本不会生效,不能依赖它来阻止用户关闭窗口。
23.2 unload 事件
unload
事件在窗口关闭或者document
对象将要卸载时触发。它的触发顺序排在beforeunload
、pagehide
事件后面。unload
事件只在页面没有被浏览器缓存时才会触发,换言之,如果通过按下“前进/后退”导致页面卸载,并不会触发unload
事件。
unload
事件发生时,文档处于一个特殊状态。所有资源依然存在,但是对用户来说都不可见,UI 互动全部无效。这个事件是无法取消的,即使在监听函数里面抛出错误,也不能停止文档的卸载。
23.3 load 事件
load
事件在页面或某个资源加载成功时触发。注意,页面或资源从浏览器缓存加载,并不会触发load
事件
error
事件是在页面或资源加载失败时触发。abort
事件在用户取消加载时触发。
这三个事件实际上属于进度事件,不仅发生在document
对象,还发生在各种外部资源上面。浏览网页就是一个加载各种资源的过程,图像(image)、样式表(style sheet)、脚本(script)、视频(video)、音频(audio)、Ajax请求(XMLHttpRequest)等等。这些资源和document
对象、window
对象、XMLHttpRequestUpload 对象,都会触发load
事件和error
事件。
24. session 历史事件
24.1 pageshow 事件,pagehide 事件
默认情况下,浏览器会在当前会话(session)缓存页面,当用户点击“前进/后退”按钮时,浏览器就会从缓存中加载页面。
pageshow 事件在页面加载时触发,包括第一次加载和从缓存加载两种情况。如果要指定页面每次加载(不管是不是从浏览器缓存)时都运行的代码,可以放在这个事件的监听函数。
第一次加载时,它的触发顺序排在load
事件后面。从缓存加载时,load
事件不会触发,因为网页在缓存中的样子通常是load
事件的监听函数运行后的样子,所以不必重复执行。同理,如果是从缓存中加载页面,网页内初始化的 JavaScript 脚本(比如 DOMContentLoaded 事件的监听函数)也不会执行。
pageshow 事件有一个persisted
属性,返回一个布尔值。页面第一次加载时,这个属性是false
;当页面从缓存加载时,这个属性是true
。
pagehide
事件与pageshow
事件类似,当用户通过“前进/后退”按钮,离开当前页面时触发。它与 unload 事件的区别在于,如果在 window 对象上定义unload
事件的监听函数之后,页面不会保存在缓存中,而使用pagehide
事件,页面会保存在缓存中。
pagehide
事件实例也有一个persisted
属性,将这个属性设为true
,就表示页面要保存在缓存中;设为false
,表示网页不保存在缓存中,这时如果设置了unload 事件的监听函数,该函数将在 pagehide 事件后立即运行。
如果页面包含<frame>
或<iframe>
元素,则<frame>
页面的pageshow
事件和pagehide
事件,都会在主页面之前触发。
24.2 popstate 事件
popstate
事件在浏览器的history
对象的当前记录发生显式切换时触发。注意,调用history.pushState()
或history.replaceState()
,并不会触发popstate
事件。该事件只在用户在history
记录之间显式切换时触发,比如鼠标点击“后退/前进”按钮,或者在脚本中调用history.back()
、history.forward()
、history.go()
时触发。
该事件对象有一个state
属性,保存history.pushState
方法和history.replaceState
方法为当前记录添加的state
对象。
上面代码中,pushState
方法向history
添加了两条记录,然后replaceState
方法替换掉当前记录。因此,连续两次back
方法,会让当前条目退回到原始网址,它没有附带state
对象,所以事件的state
属性为null
,然后前进两条记录,又回到replaceState
方法添加的记录。
浏览器对于页面首次加载,是否触发popstate
事件,处理不一样,Firefox 不触发该事件。
24.3 hashchange 事件
hashchange
事件在 URL 的 hash 部分(即#
号后面的部分,包括#
号)发生变化时触发。该事件一般在window
对象上监听。
hashchange
的事件实例具有两个特有属性:oldURL
属性和newURL
属性,分别表示变化前后的完整 URL。
25. 网页状态事件
25.1 DOMContentLoaded 事件
网页下载并解析完成以后,浏览器就会在document
对象上触发 DOMContentLoaded 事件。这时,仅仅完成了网页的解析(整张页面的 DOM 生成了),所有外部资源(样式表、脚本、iframe 等等)可能还没有下载结束。也就是说,这个事件比load
事件,发生时间早得多。
注意,网页的 JavaScript 脚本是同步执行的,脚本一旦发生堵塞,将推迟触发DOMContentLoaded
事件。
25.2 readystatechange 事件
readystatechange
事件当 Document 对象和 XMLHttpRequest 对象的readyState
属性发生变化时触发。document.readyState
有三个可能的值:
loading
(网页正在加载) interactive
(网页已经解析完成,但是外部资源仍然处在加载状态) complete
(网页和所有外部资源已经结束加载,load
事件即将触发)
这个事件可以看作DOMContentLoaded
事件的另一种实现方法。
26. 窗口事件
scroll
事件在文档或文档元素滚动时触发,主要出现在用户拖动滚动条。
该事件会连续地大量触发,所以它的监听函数之中不应该有非常耗费计算的操作。推荐的做法是使用requestAnimationFrame
或setTimeout
控制该事件的触发频率,然后可以结合customEvent
抛出一个新事件。
上面代码中,throttle
函数用于控制事件触发频率,requestAnimationFrame
方法保证每次页面重绘(每秒60次),只会触发一次scroll
事件的监听函数。也就是说,上面方法将scroll
事件的触发频率,限制在每秒60次。具体来说,就是scroll
事件只要频率低于每秒60次,就会触发optimizedScroll
事件,从而执行optimizedScroll
事件的监听函数。
改用setTimeout
方法,可以放置更大的时间间隔。
上面代码中,每次scroll
事件都会执行scrollThrottler
函数。该函数里面有一个定时器setTimeout
,每66毫秒触发一次(每秒15次)真正执行的任务actualScrollHandler
。
下面是一个更一般的throttle
函数的写法。
上面的代码将scroll
事件的触发频率,限制在一秒一次。
lodash
函数库提供了现成的throttle
函数,可以直接使用。
26.2 resize 事件
resize
事件在改变浏览器窗口大小时触发,主要发生在window
对象上面。
该事件也会连续地大量触发,所以最好像上面的scroll
事件一样,通过throttle
函数控制事件触发频率。
26.3 fullscreenchange 事件,fullscreenerror 事件
fullscreenerror
事件在浏览器无法切换到全屏状态时触发。
27. 剪贴板事件
以下三个事件属于剪贴板操作的相关事件。
cut
:将选中的内容从文档中移除,加入剪贴板时触发。 copy
:进行复制动作时触发。 paste
:剪贴板内容粘贴到文档后触发。
这三个事件都是ClipboardEvent
接口的实例。ClipboardEvent
有一个实例属性clipboardData
,是一个 DataTransfer 对象,存放剪贴的数据。具体的 API 接口和操作方法,请参见《触摸事件》的 DataTransfer 对象部分。
上面代码执行后,在页面复制(cmd + c), 然后在别的地方粘贴的内容会是Hello, world!
.
上面的代码使得复制进入剪贴板的,都是开发者指定的数据,而不是用户想要拷贝的数据。
28. 焦点事件
焦点事件发生在元素节点和document
对象上面,与获得或失去焦点相关。它主要包括以下四个事件。
focus
:元素节点获得焦点后触发,该事件不会冒泡。 blur
:元素节点失去焦点后触发,该事件不会冒泡。 focusin
:元素节点将要获得焦点时触发,发生在focus
事件之前。该事件会冒泡。 focusout
:元素节点将要失去焦点时触发,发生在blur
事件之前。该事件会冒泡。
这四个事件都继承了FocusEvent
接口。FocusEvent
实例具有以下属性。
FocusEvent.target
:事件的目标节点。 FocusEvent.relatedTarget
:对于focusin
事件,返回失去焦点的节点;对于focusout
事件,返回将要接受焦点的节点;对于focus
和blur
事件,返回null
。
由于focus
和blur
事件不会冒泡,只能在捕获阶段触发,所以addEventListener
方法的第三个参数需要设为true
。
上面代码针对表单的文本输入框,接受焦点时设置背景色,失去焦点时去除背景色。
29. 参考资料
事件 阮一峰 网道
事件种类 阮一峰
在线代码测试 JSbin