我正在尝试在表格上实现动态列大小调整(例如在Excel或Google表格中)。
在渲染功能中,当用户在调整大小控件上单击鼠标时,我使用handle
回调:
<div
className="resizer"
onMouseDown={self.handle(handleColumnResizeStart)}
/>
在处理程序中,我想为mousemove添加一个新的事件侦听器,以便在用户“拖动”时可以绘制一些内容以指示新的列边缘将在何处结束。
我当时以为在mousemove处理程序中,我可以发送一个reducer动作,该动作包含鼠标clientX坐标来更新组件状态,以便渲染函数在拖动时可以绘制一些东西。
let handleColumnResizeStart = (evt, self) => {
/* this handler gets invoked when the mouse is moved */
let handleMouseMove = evt => {
Js.log(evt); /* in js land I can see that clientX is in that evt object */
Js.log(ReactEvent.Mouse.clientX(evt)); /* but this creates type errors */
};
/* adds an event handler using the bs-webapi module */
Webapi.Dom.EventTarget.addEventListener(
"mousemove",
handleMouseMove,
document,
);
};
当我尝试使用ReactEvent.Mouse.clientX(evt)
获取clientX的特定int值时,出现此错误:
25 Webapi.Dom.EventTarget.removeEventListener(
26 ┆ "mousemove",
27 ┆ handleMouseMove,
28 ┆ document,
29 ┆ );
This has type:
ReactEvent.Mouse.t => unit
But somewhere wanted:
Dom.event => unit
The incompatible parts:
ReactEvent.Mouse.t (defined as
ReactEvent.synthetic(ReactEvent.Mouse.tag))
vs
Dom.event (defined as Dom.event_like(Dom._baseClass))
>>>> Finish compiling(exit: 1)
我对类型系统的了解仅限于此,我不确定如何将鼠标clientX坐标的值转换为变量。
答案 0 :(得分:4)
尽管从React和直接附加到DOM的事件处理程序接收的事件可能看起来很相似,但实际上它们是不同的。 React不会给您一个原始的DOM事件,而是一个SyntheticEvent,因此,由于某种原因,它们被赋予了不同的类型,这就是类型错误通知您的原因。您不能在期望Dom.event
的地方使用ReactEvent.Mouse.t
。在这种情况下,evt
是Dom.event
,因为它是通过使用bs-webapi
将事件处理程序直接附加到DOM来获取的,并且ReactEvent.Mouse.clientX
当然期望{{1} }。
因此,应该使用ReactEvent.Mouse.t
而不是使用ReactEvent.Mouse.clientX
。
不幸的是,这仍然行不通,因为Webapi.Dom.MouseEvent.clientX
期望使用Webapi.Dom.MouseEvent.clientX
而不是Dom.mouseEvent
,它是所有DOM事件类型的超类型,并且太笼统而无法与函数一起使用特定于鼠标事件。这又是因为Dom.event
无法理解Webapi.Dom.EventTarget.addEventLsitener
是鼠标事件。相反,您应该使用"mousemove"
,它确实会给您Webapi.Dom.EventTarget.addMouseMoveEventListener
。
请注意,您得到的类型错误比它需要的更加混乱,因为它会推断出类型并指向错误,而不是您认为错误源于何处。注释类型是一个好主意,至少在遇到难以理解的类型错误时。这样,编译器就不会推断出您不希望的类型,并且会包含错误的来源。
您可能还想使用Dom.mouseEvent
而不是Webapi.Dom.Document
。 Webapi.Dom.EventTarget
继承了Document
中的所有内容,但会记录并约束您所操作的类型。