Web-UI Event
Zhongjun Qiu 元婴开发者

本文系统梳理了 Web 中的鼠标、键盘与指针事件机制,包括事件触发顺序、事件属性、组合键判断、坐标获取、防止默认行为,以及拖放操作与 Pointer Events 的使用。同时,解析了 event.key 与 event.code 的区别,帮助开发者更精准地处理 UI 交互逻辑。

鼠标事件

事件顺序

从上面的列表中我们可以看到,一个用户操作可能会触发多个事件。

例如,点击鼠标左键,在鼠标左键被按下时,会首先触发 mousedown,然后当鼠标左键被释放时,会触发 mouseupclick

在单个动作触发多个事件时,事件的顺序是固定的。也就是说,会遵循 mousedownmouseupclick 的顺序调用处理程序。

鼠标按钮

与点击相关的事件始终具有 button 属性,该属性允许获取确切的鼠标按钮。

通常我们不在 clickcontextmenu 事件中使用这一属性,因为前者只在单击鼠标左键时触发,后者只在单击鼠标右键时触发。

不过,在 mousedownmouseup 事件中则可能需要用到 event.button,因为这两个事件在任何按键上都会触发,所以我们可以使用 button 属性来区分是左键单击还是右键单击。

event.button 的所有可能值如下:

鼠标按键状态 event.button
左键 (主要按键) 0
中键 (辅助按键) 1
右键 (次要按键) 2
X1 键 (后退按键) 3
X2 键 (前进按键) 4

大多数鼠标设备只有左键和右键,对应的值就是 02。触屏设备中的点按操作也会触发类似的事件。

组合键:shift,alt,ctrl,meta

所有的鼠标事件都包含有关按下的组合键的信息。

  • shiftKey:Shift
  • altKey:Alt(或对于 Mac 是 Opt)
  • ctrlKey:Ctrl
  • metaKey:对于 Mac 是 Cmd

如果在事件期间按下了相应的键,则它们为 true

比如,下面这个按钮仅在 Alt+Shift+click 时才有效:

1
2
3
4
5
6
7
8
9
<button id="button">Alt+Shift+Click on me!</button>

<script>
button.onclick = function (event) {
if (event.altKey && event.shiftKey) {
alert("Hooray!");
}
};
</script>

坐标:clientX/Y,pageX/Y

所有的鼠标事件都提供了两种形式的坐标:

  1. 相对于窗口的坐标:clientXclientY
  2. 相对于文档的坐标:pageXpageY

防止在鼠标按下时的选择

双击鼠标会有副作用,在某些界面中可能会出现干扰:它会选择文本。

比如,双击下面的文本,除了我们的处理程序外,还会选择文本:

1
<span ondblclick="alert('dblclick')">Double-click me</span>

如果按下鼠标左键,并在不松开的情况下移动鼠标,这也常常会造成不必要的选择。

在这种情况下,最合理的方式是防止浏览器对 mousedown 进行操作。这样能够阻止刚刚提到的两种选择:

1
2
3
Before...
<b ondblclick="alert('Click!')" onmousedown="return false"> Double-click me </b>
...After

如果我们想禁用选择以保护我们页面的内容不被复制粘贴,那么我们可以使用另一个事件:oncopy

1
2
3
4
<div oncopy="alert('Copying forbidden!');return false">
Dear user, The copying is forbidden for you. If you know JS or HTML, then
you can get everything from the page source though.
</div>

移动鼠标:mouseover/out,mouseenter/leave

当鼠标指针移到某个元素上时,mouseover 事件就会发生,而当鼠标离开该元素时,mouseout 事件就会发生。

事件 mouseenter/mouseleave 类似于 mouseover/mouseout。它们在鼠标指针进入/离开元素时触发。

但是有两个重要的区别:

  1. 元素内部与后代之间的转换不会产生影响。
  2. 事件 mouseenter/mouseleave 不会冒泡。

鼠标拖放事件

  1. 事件流:ball.mousedowndocument.mousemoveball.mouseup(不要忘记取消原生 ondragstart)。
  2. 在拖动开始时 —— 记住鼠标指针相对于元素的初始偏移(shift):shiftX/shiftY,并在拖动过程中保持它不变。
  3. 使用 document.elementFromPoint 检测鼠标指针下的 “droppable” 的元素。

我们可以在此基础上做很多事情。

  • mouseup 上,我们可以智能地完成放置(drop):更改数据,移动元素。
  • 我们可以高亮我们正在“飞过”的元素。
  • 我们可以将拖动限制在特定的区域或者方向。
  • 我们可以对 mousedown/up 使用事件委托。一个大范围的用于检查 event.target 的事件处理程序可以管理数百个元素的拖放。

指针事件

指针事件(Pointer Events)是一种用于处理来自各种输入设备(例如鼠标、触控笔和触摸屏等)的输入信息的现代化解决方案。

指针事件类型

指针事件 类似的鼠标事件
pointerdown mousedown
pointerup mouseup
pointermove mousemove
pointerover mouseover
pointerout mouseout
pointerenter mouseenter
pointerleave mouseleave
pointercancel -
gotpointercapture -
lostpointercapture -

不难发现,每一个 mouse<event> 都有与之相对应的 pointer<event>

指针事件属性

指针事件具备和鼠标事件完全相同的属性,包括 clientX/Ytarget 等,以及一些其他属性:

  • pointerId —— 触发当前事件的指针唯一标识符。

    浏览器生成的。使我们能够处理多指针的情况,例如带有触控笔和多点触控功能的触摸屏(下文会有相关示例)。

  • pointerType —— 指针的设备类型。必须为字符串,可以是:“mouse”、“pen” 或 “touch”。

    我们可以使用这个属性来针对不同类型的指针输入做出不同响应。

  • isPrimary —— 当指针为首要指针(多点触控时按下的第一根手指)时为 true

键盘:keydown 和 keyup

当一个按键被按下时,会触发 keydown 事件,而当按键被释放时,会触发 keyup 事件。

event.code 和 event.key

事件对象的 key 属性允许获取字符,而事件对象的 code 属性则允许获取“物理按键代码”。

例如,同一个按键 Z,可以与或不与 Shift 一起按下。我们会得到两个不同的字符:小写的 z 和大写的 Z

event.key 正是这个字符,并且它将是不同的。但是,event.code 是相同的:

Key event.key event.code
Z z(小写) KeyZ
Shift+Z Z(大写) KeyZ

如果用户使用不同的语言,那么切换到另一种语言将产生完全不同的字符,而不是 "Z"。它将成为 event.key 的值,而 event.code 则始终都是一样的:"KeyZ"

 REWARD AUTHOR
 Comments
Comment plugin failed to load
Loading comment plugin