一、描述

下面更多的是对 API 部分的说明,基础的事件处理文档在 React 文档的 Handling Events 部分。

SyntheticEvent 是 React 在浏览器事件基础上做的一层包装器,基本上 SyntheticEvent 和浏览器的原生事件有相同的接口,也能够进行 stopPropagation()preventDefault(),并且事件在所有浏览器中的工作方式相同。

如果由于某种原因需要浏览器的原生事件,则能够简单的通过 nativeEvent 属性就能够获取,每个 SynctheticEvent 对象都有如下的属性(下面属性是一定包含的,不同的事件包含的属性又会有新增):

类型属性名
booleanbubbles
booleancancelable
DOMEventTargetcurrentTarget
booleandefaultPrevented
numbereventPhase
booleanisTrusted
DOMEventnativeEvent
voidpreventDefault()
booleanisDefaultPrevented()
voidstopPropagation()
booleanisPropagationStopped()
DOMEventTargettarget
numbertimeStamp
stringtype

注意:

从 ReactV0.14 起,从事件处理程序返回 false 将不再停止时间的传递。应当手动调用 e.stopPropagation()e.preventDefault() 去阻止传递。

二、事件池(Event Pooling)

SyntheticEvent 是在事件池中的,这意味着将重用 SynctheticEvent 对象,并且在调用事件回调后,所有的实行都将无效。这是处于性能考虑而实现的一种方式,所以,事件是不能以异步方式访问的。

比如下面的代码输出:

  clickHandle = (e) => {
    console.log(e);
    console.log(e.type);
    setTimeout(() => {
      console.log(e);
      console.log(e.type);
    }, 10);
  }

111.png

上面截图中不仅有一个 warning,在异步中 event.type 会返回 null,因此,如果在异步中要使用诸如 event.type 的属性,建议是通过一个 常量 来保存。

因为这种事件池的特性, 也不能直接使用 this.setState({event:event}) 来保存 event 对象,因为 setState 是异步的,没办法直接保存 event 对象。但是直接保存 event.type 是可行的。

如果需要异步访问事件属性,应在事件上调用 event.persist(),这种操作将从事件池中删除 SyncthesicEvent,并允许用户代码保留对事件的引用。

下面代码中直接调用 e.persist(),这在某些有网络请求的事件中可能是有帮助的:

clickHandle = (e) => {
    e.persist();
    console.log(e);
    console.log(e.type);
    setTimeout(() => {
      console.log(e);
      console.log(e.type);
    }, 100);
  }

222.png

三、支持的事件

React 规范化事件,以便在不同的浏览器中能够表现一致,有一致的属性。

下面的事件处理程序由冒泡阶段的事件触发。如果要在捕获阶段注册事件处理程序,需要将 Capture 附加到事件名称,比如,可以通过 onClickCapture 用来处理 捕获阶段 的 click 事件,而不是使用 onClick

  • Clipboard Events
  • Composition Events
  • Keyboard Events
  • Focus Events
  • Form Events
  • Mouse Events
  • Pointer Events
  • Selection Events
  • Touch Events
  • UI Events
  • Wheel Events
  • Media Events
  • Image Events
  • Animation Events
  • Transition Events
  • Other Events

1、剪贴板事件

事件名:

  • onCopy
  • onCut
  • onPaste

多出的属性:

DOMDataTransfer clipboardData

以 copy 事件举例:

333.png

2、Composition 事件

  • onCompositionEnd
  • onCompositionStart
  • onCompositionUpdate

多出的属性:

string data

3、键盘事件

  • onKeyDown
  • onKeyPress
  • onKeyUp

多出的属性:

类型属性名
booleanaltKey
numbercharCode
booleanctrlKey
booleangetModifierState(key)
stringkey
numberkeyCode
stringlocale
numberlocation
booleanmetaKey
booleanrepeat
booleanshiftKey
numberwhich

关键的属性是遵循 DOM 3 级事件规范

比如一个 Enter 按键:

  onKeyDownHandle = (e) => {
    console.log("altKey " + e.altKey);
    console.log("charCode " + e.charCode);
    console.log("ctrlKey " + e.ctrlKey);
    console.log("key " + e.key);
    console.log("keyCode " + e.keyCode);
    console.log("locale " + e.locale);
    console.log("location " +e.location);
    console.log("metaKey " + e.metaKey);
    console.log("repeat " +e.repeat);
    console.log("shiftKey " + e.shiftKey);
    console.log("which " + e.which);
  }

444.png

4、Focus 事件

  • onFocus
  • onBlur

焦点事件适用于 React DOM 中的所有元素,而不仅仅是表单元素。

属性:

DOMEventTarget relatedTarget

5、Form 事件

  • onChange
  • onInput
  • onInvalid
  • onSubmit

关于表单事件就不重复太多了,直接看 React 的 Forms 文档 就行

需要注意的是 onChange 和在浏览器上的 oninput 表现是一致的。

5、鼠标事件

  • onClick
  • onContextMenu
  • onDoubleClick
  • onDrag
  • onDragEnd
  • onDragEnter
  • onDragExit
  • onDragLeave
  • onDragOver
  • onDragStart
  • onDrop
  • onMouseDown
  • onMouseEnter
  • onMouseLeave
  • onMouseMove
  • onMouseOut
  • onMouseOver
  • onMouseUp

onMouseEnteronMouseLeave 事件从左边的元素传播到正在输入的元素,而不是普通的冒泡行为,并且两个事件是没有捕获阶段的。

属性:

类型属性名
booleanaltKey
numberbutton
number `buttons`
number clientX
numberclientY
boolean ctrlKey
booleangetModifierState(key)
boolean metaKey
numberpageX
numberpageY
DOMEventTargetrelatedTarget
numberscreenX
numberscreenY
booleanshiftKey

6、指针事件

  • onPointerDown
  • onPointerMove
  • onPointerUp
  • onPointerCancel
  • onGotPointerCapture
  • onLostPointerCapture
  • onPointerEnter
  • onPointerLeave
  • onPointerOver
  • onPointerOut

onPointerEnteronPointerLeave 事件从左边元素传播到正在输入的元素,而不是普通的冒泡行为,而且没有捕获阶段。

属性:

类型属性名
numberpointerId
number width
numberheight
numberpressure
numbertangentialPressure
numbertiltX
number tiltY
numbertwist
stringpointerType
booleanisPrimary

跨浏览器支持的说明:

Pointer 事件不是所有浏览器都支持的(目前支持的浏览器包括:Chrome,Firefox,Edge和Internet Explorer),因此 React 也米有对其他浏览器做 polyfill,因为会增加 react-dom 的 bundle 的大小。如果需要使用 Pointer 事件,需要使用第三方的事件 polyfill。

7、选择事件

  • onSelect

8、Touch 事件

  • onTouchCancel
  • onTouchEnd
  • onTouchMove
  • onTouchStart

属性:

类型属性名
booleanaltKey
DOMTouchList changedTouches
booleanctrlKey
booleangetModifierState(key)
booleanmetaKey
booleanshiftKey
DOMTouchList targetTouches
DOMTouchList touches

9、UI 事件

  • onScroll
属性类型属性名
number detail
DOMAbstractView view

10、鼠标滚轮事件

  • onWheel
属性类型属性名
numberdeltaMode
numberdeltaX
numberdeltaY
numberdeltaZ

10、媒体事件

  • onAbort
  • onCanPlay
  • onCanPlayThrough
  • onDurationChange
  • onEmptied
  • onEncrypted
  • onEnded
  • onError
  • onLoadedData
  • onLoadedMetadata
  • onLoadStart
  • onPause
  • onPlay
  • onPlaying
  • onProgress
  • onRateChange
  • onSeeked
  • onSeeking
  • onStalled
  • onSuspend
  • onTimeUpdate
  • onVolumeChange
  • onWaiting

11、图片事件

  • onLoad
  • onError

12、动画事件

  • onAnimationStart
  • onAnimationEnd
  • onAnimationIteration
属性类型属性名
stringanimationName
stringpseudoElement
floatelapsedTime

13、过渡事件

  • onTransitionEnd
属性类型属性名

string| propertyName|
|string| pseudoElement|
|float| elapsedTime|

14、其他事件

  • onToggle

ontoggle<details> DOM 的事件