这个页面详细介绍了我们如何使用DOM输入事件,我们对它们做了什么,以及如何在我们的使用之上构建工作。通常,您不需要知道此信息但是,如果您还将自己的事件处理程序绑定到 window 或 一个拖动控制,这些信息会有用。
⚠️ 注意:由于webkit中的一个错误,特别是当event.preventDefault()
被调用,诸如类mousemove
事件将无法正确设event.defaultPrevented
为true
。您可以关注此问题的进展在这里.
本页假定您具有DOM事件的工作知识。有关DOM事件的详细介绍,请参阅:
无需深入了解下面的所有细节,这里是react-beautiful-dnd
最上层的最高安全的事件处理程序:
这些都可以添加到拖动控制,'树'上任何其他地方或直接在window.
onClick
:如果作为拖动交互部分发生了,event.defaultPrevented
属性将设置为true
。即使拖动未完成诸如mouseup
或touchend
之类的预先单击操作。看马虎点击和点击预防.onKeyDown
:如果它被用作拖拽的一部分,event.defaultPrevented
属性将设置为true
。如果你想添加onKeyDown
到拖动控制,你将需要猴子补丁 下DragHandleProps
onKeyDown
事件处理程序
您可能需要使用来自onDragStart
和onDragEnd
的信息来提高事件处理程序的逻辑了解,明确知道在这些事件发生时,是否为一个拖动了.
欢迎您添加其他事件处理程序,但您可能更需要onDragStart
和onDragEnd
的信息.
当我们使用输入事件作为拖放交互的一部分时,我们通常会调用event.preventDefault()
函数,此函数会退出标准浏览器的事件行为。当调用event.preventDefault()
,也不会停止我们事件的传播,所有即使我们使用一个mousemove
拖动事件,我们也不会阻止该事件发布(传播),最后被您的事件处理程序接收.
- 我们用:
event.preventDefault()
- 我们不使用:
event.stopPropagation()
我们添加了一些事件处理程序到拖动控制本身(见DragHandleProps
)和我们又添加了其他的到window
在里面捕获阶段。这意味着只要您在冒泡阶段中使用事件处理程序(这是事件处理程序的默认设置),然后事件的行为将如此页面所述.
为了知道我们是否已经把事件用在了拖放功能,您需要检查event.defaultPrevented
属性.
所以假设你要添加一个window的click
处理程序。你可以这样做:
window.addEventListener('click', (event: MouseEvent) => {
// 事件 已用于 drag 和 drop
if (event.defaultPrevented) {
return;
}
doMyCoolThing();
});
某些用户事件会对拖动有直接影响:例如当鼠标拖动时的一个mousemove
或用键盘向上箭头 ↑拖动时的keydown
事件。这些直接事件都会有event.preventDefault()
的调用,以此来阻止他们的默认浏览器行为。有些事件则会间接影响了,如当取消拖动时的resize
事件之类。对于间接影响拖动的事件,并不会调用event.preventDefault()
。影响拖拽的间接事件通常以取消拖动为主,例如reize
或orientationchange
事件.
preventDefault()
会 被调用😞
这是我们规则集合中的唯一已知的例外。不幸的是,这只是第一个!
当用户第一次在拖动控制上触及mousedown
时,我们不确定他们是否打算点击或拖动。理想情况下,我们不会调用preventDefault()
,因为我们不确定它是否是拖动的一部分.但是,我们需要调用preventDefault()
,这样是为了避免项目获得焦点,因为它有一个tabIndex
.
preventDefault()
没有被调用
在我们将运动视为拖动之前,用户需要移动一个小阈值。在这段时间我们不会在任何
mousemove事件调用
preventDefault(),因为我们不确定他们是拖动还是,只是马虎点击
preventDefault()
没有调用,因有让拖动结束的事件(例如mouseup
和keydown
)。在有挂起拖动时,任何keydown
事件被激活将被视为间接取消拖动preventDefault()
并不调用在随后的click
事件,如果有的话
preventDefault()
在mousemove
事件中被调用preventDefault()
在少数keydown
事件中被调用,阻止其标准浏览器行为的事件preventDefault()
在keyup
事件中没有被调用,即使keydown
被阻止了
preventDefault()
在一个mouseup
中被调用,如果它结束了拖动preventDefault()
在退出 esckeydown
中被调用,如果因为它直接结束拖动preventDefault()
在下一个click
事件时被调用,不管拖动是如何结束,都会发生事件.看马虎点击和点击预防preventDefault()
不会在其他事件上调用,如resize
间接结束了拖动preventDefault()
在keyup
事件不会被调用,即使它们导致拖动结束
触摸拖动的逻辑与鼠标拖动的工作方式类似
preventDefault()
在touchstart
没有被调用.
当用户在Draggable
上按下他们的手指(或其他输入)时,我们不确定他们是否打算去单点,重压,滚屏要么拖动。因为我们不知道用户想要做什么, 反正我们不调用preventDefault()
在这个事件上.
preventDefault()
不会在任何事件上被调用
用户可以通过将手指👇在元素组件上保持一小段时间🕑(长按)来开始拖动.如果用户在这段时间内,移动了,触发touchmove
事件,那我们在这个事件上不调用preventDefault()
.
可通过如一个orientationchange
或者一个touchcancel
之类的时间取消触摸拖动。在这些事件上我们都不会调用preventDefault
.
preventDefault()
在touchmove
事件上被调用
✌️
preventDefault()
在touchend
事件上被调用preventDefault()
在touchcancel
事件上被调用preventDefault()
在作为直接取消的退出 esckeydown
上调用。preventDefault()
在任何其他keydown
事件不调用,因为哪些事件是间接取消.preventDefault()
不会在其他如orientationchange
事件上调用,因其可取消拖动
- 如果拖动尚未开始,
preventDefault()
没有被调用touchforcechange
- 如果拖动已经开始但尚未发生移动,
preventDefault()
没有被调用touchforcechange
。重压会取消拖动且是间接取消. - 在拖动的
touchforcechange
已经开始和touchmove
已经结束了之后,preventDefault()
调用。这是为了防范touchmove
之后touchforcechange
不应该发生.
我们只用
keydown
事件应对用于键盘拖动,所以keyup
事件中从来没有调用过preventDefault()
preventDefault()
在keydown
被调用
与鼠标拖动不同,键盘拖动会在用户按下空格键 空间时,立即开始。这个初始的键盘交互就会有event.preventDefault()
调用.
- 如果事件被用作拖动的一部分(例如向上箭头 ↑),
preventDefault()
在keydown
被调用 - 当我们想要阻止标准浏览器行为(例如
enter
键入),preventDefault()
在keydown
事件被调用 - 若我们不用于拖动的事件,
preventDefault()
在keydown
上没有被调用,
- 如果是空格键 space键的话,
preventDefault()
在keydown
被调用,因为它正在放下 - 如果是退出 esc键的话,
preventDefault()
在keydown
被调用,因为它明确取消拖动 preventDefault()
不会在间接取消拖动的事件上调用,例如resize
要么mousedown
.