UI事件
在这里,我们介绍了最重要的用户界面事件,以及如何使用它们。
鼠标事件
在本章中,我们将详细介绍鼠标事件及其属性。
请注意:此类事件不仅可能来自于“鼠标设备”,还可能来自于对此类操作进行了模拟以实现兼容性的其他设备,例如手机和平板电脑。
鼠标事件有以下属性:
按钮:
button
组合键(如果被按下则为 true):
altKey
,ctrlKey
,shiftKey
和metaKey
(Mac)。- 如果你想处理
Ctrl
,那么不要忘记 Mac 用户,他们通常使用的是Cmd
,所以最好检查if (e.metaKey || e.ctrlKey)
。
- 如果你想处理
窗口相对坐标:
clientX/clientY
。文档相对坐标:
pageX/pageY
。
mousedown
的默认浏览器操作是文本选择,如果它对界面不利,则应避免它。
在下一节中,我们将看到有关鼠标指针移动后的事件,以及如何跟踪其下元素变化的更多详细信息。
移动鼠标
我们将深入研究鼠标在元素之间移动时发生的事件。
以下这些内容要注意:
- 快速移动鼠标可能会跳过中间元素。
mouseover/out
和mouseenter/leave
事件还有一个附加属性:relatedTarget。这就是我们来自/到的元素,是对 target 的补充。
即使我们从父元素转到子元素时,也会触发 mouseover/out
事件。浏览器假定鼠标一次只会位于一个元素上 —— 最深的那个。
mouseenter/leave
事件在这方面不同:它们仅在鼠标进入和离开元素时才触发。并且它们不会冒泡。
鼠标拖放事件
我们考虑了一种基础的拖放算法。
关键部分:
- 事件流:
ball.mousedown
→document.mousemove
→ball.mouseup
(不要忘记取消原生ondragstart
)。 - 在拖动开始时 —— 记住鼠标指针相对于元素的初始偏移(shift):
shiftX/shiftY
,并在拖动过程中保持它不变。 - 使用
document.elementFromPoint
检测鼠标指针下的“droppable”
的元素。 我们可以在此基础上做很多事情。
- 在
mouseup
上,我们可以智能地完成放置(drop):更改数据,移动元素。 - 我们可以高亮我们正在“飞过”的元素。
- 我们可以将拖动限制在特定的区域或者方向。
- 我们可以对
mousedown/up
使用事件委托。一个大范围的用于检查event.target
的事件处理程序可以管理数百个元素的拖放。 - 等等。
有一些在此基础上已经将体系结构构建好的框架:DragZone
,Droppable
,Draggable
及其他 class
。它们中的大多数做的都是与上述类似的事情,所以现在你应该很容易理解它们了。或者自己动手实现。正如你所看到的,其实挺简单的,有时候比基于第三方解决方案进行改写还容易。
指针事件
指针事件(Pointer Events)是一种用于处理来自各种输入设备(例如鼠标、触控笔和触摸屏等)的输入信息的现代化解决方案。
指针事件允许我们通过一份代码,同时处理鼠标、触摸和触控笔事件。
指针事件是鼠标事件的拓展。我们可以在事件名称中用 pointer
替换 mouse
来让我们的代码既能继续支持鼠标,也能更好地支持其他类型的设备。
对于浏览器可能会决定进行劫持并自行处理的拖放和复杂的触控交互 —— 请记住取消事件的默认操作,并在 CSS 中为涉及到的元素设置 touch-action: none
。
指针事件还额外具备以下能力:
- 基于
pointerId
和isPrimary
的多点触控支持。 - 针对特定设备的属性,例如
pressure
和width/height
等。 - 指针捕获:我们可以把
pointerup/pointercancel
之前的所有指针事件重定向到一个特定的元素。
目前,指针事件已经被各大主流浏览器支持,尤其是如果不需要支持 IE10 和 Safari 12 以下的版本,我们可以放心地使用它们。不过即便是针对这些老式浏览器,也可以通过 polyfill 来让它们支持指针事件。
键盘:keydown 和 keyup
按一个按键总是会产生一个键盘事件,无论是符号键,还是例如 Shift 或 Ctrl 等特殊按键。唯一的例外是有时会出现在笔记本电脑的键盘上的 Fn 键。它没有键盘事件,因为它通常是被在比 OS 更低的级别上实现的。
键盘事件:
keydown
—— 在按下键时(如果长按按键,则将自动重复),keyup
—— 释放按键时。
键盘事件的主要属性:
code
—— “按键代码”("KeyA","ArrowLeft" 等),特定于键盘上按键的物理位置。key
—— 字符("A","a" 等),对于非字符(non-character)的按键,通常具有与 code 相同的值。
过去,键盘事件有时会被用于跟踪表单字段中的用户输入。这并不可靠,因为输入可能来自各种来源。我们有 input 和 change 事件来处理任何输入(稍后我们会在 事件:change,input,cut,copy,paste
一章中进行介绍)。它们在任何类型的输入(包括复制粘贴或语音识别)后触发。
当我们真的想要键盘时,我们应该使用键盘事件。例如,对热键或特殊键作出反应。
滚动
scroll 事件允许对页面或元素滚动作出反应。我们可以在这里做一些有用的事情。
例如:
- 根据用户在文档中的位置显示/隐藏其他控件或信息。
- 当用户向下滚动到页面末端时加载更多数据。
这是一个显示当前滚动的小函数:
window.addEventListener('scroll', function() {
document.getElementById('showScroll').innerHTML = window.pageYOffset + 'px';
});
在运行中:
Current scroll = 0px
scroll 事件在 window 和可滚动元素上都可以运行。
我们如何使某些东西变成不可滚动?
我们不能通过在 onscroll
监听器中使用 event.preventDefault()
来阻止滚动,因为它会在滚动发生 之后 才触发。
但是我们可以在导致滚动的事件上,例如在 pageUp
和 pageDown
的 keydown
事件上,使用 event.preventDefault()
来阻止滚动。
如果我们向这些事件中添加事件处理程序,并向其中添加 event.preventDefault()
,那么滚动就不会开始。
启动滚动的方式有很多,使用 CSS 的 overflow 属性更加可靠。