跳到主要内容

参考约 9 分钟

支持的事件

全部事件属性与载荷字段、指针捕获的触发规则,以及滚轮不冒泡这一点。

事件 属性 载荷字段
点击 onClick x, y, button, clickCount, isRightClick, modifiers — 仅主键
辅助点击 onAuxClick x, y, clickCount, isRightClick, modifiers — 非主键
鼠标按下 onMouseDown x, y, button, clickCount, modifiers
鼠标抬起 onMouseUp x, y, button, clickCount, modifiers
鼠标进入 onMouseEnter hovered
鼠标离开 onMouseLeave hovered
鼠标移动 onMouseMove x, y, pressedButton, modifiers
外侧点击 onMouseDownOutside x, y, button, modifiers
按键按下 onKeyDown key, keyChar, isHeld, modifiers
按键抬起 onKeyUp key, keyChar, modifiers
获得焦点 onFocus —
失去焦点 onBlur —
滚动 onScroll deltaX, deltaY, precise, touchPhase, modifiers
文件拖入 onFileDrop paths, x, y — 来自 Finder 或系统的 Unicode 文件系统路径
变更 onChange value — 仅 <input> 与 <textarea>
提交 onSubmit value — <input> 始终触发,<textarea> 在设置了 onSubmit 时触发
切换文件 onToggleFile value(文件路径)— 仅 <diff>
展开更多 onShowMore value(隐藏行数)— 仅 <diff>
行点击 onLineClick value, oldLine, newLine — 仅 <diff>
链接点击 onLinkClick value(URL)— 仅 <markdown>
选区变更 onSelectionChange value(拼接后的选中文本)— render() 上的窗口级事件

键盘与焦点监听器会自动创建一个持久的 GPUI FocusHandle。仅加监听器并不会把 div 放进 Tab 顺序;为此要加上 tabIndex={0}。输入框与多行文本框已经使用 tab index 0。

监听器可以放在哪里

把监听器放在 div、text、img、svg、input、textarea、code、markdown、diff 或 anchored 上。

<virtual-list> 不接受该事件,请把它包起来:

<div
  onFileDrop={(event) => openFiles(event.paths ?? [])}
  style={{ width: 400, height: 300 }}
>
  <virtual-list estimatedItemHeight={24}>{rows}</virtual-list>
</div>

文件拖放

来自 Finder 或系统的文件拖放会落在注册了 onFileDrop 的悬停元素上。paths 是绝对 Unicode 文件系统路径的数组。x 和 y 是窗口像素坐标系下的拖放落点。空拖放,或拖放中包含非 Unicode 路径时,不会触发。

指针捕获

同时监听 onMouseDown 和 onMouseMove 的节点会捕获指针,类似 HTML 的 setPointerCapture。在指针离开命中区、离开父级、离开窗口之后,onMouseMove 和 onMouseUp 仍会继续触发。只有 onMouseDown / onMouseUp 的节点不会捕获,所以在外部松开时点击依然会结束。

捕获由按下动作本身触发,所以请把三个监听器都放在用户抓取的那个元素上:

<div
  style={{ cursor: 'grab', active: { cursor: 'grabbing' } }}
  onMouseDown={(e) => beginDrag(e)}
  onMouseMove={(e) => moveDrag(e)}
  onMouseUp={endDrag}
/>

捕获仅在左键按下时触发。右键拖拽不会被捕获,因此指针离开元素时就会结束。

onClick 在左键松开时触发。其它按键请用 onAuxClick 并读取 event.isRightClick。onMouseDown 与 onMouseUp 通过 event.button(0 左键、1 中键、2 右键)能看到每一个按键。

滚轮不冒泡

<anchored> 默认就会遮挡,并有独立的 occlude prop,因此菜单与 tooltip 两者都不需要自己处理这件事。

一个填充了内容、位于点击目标内部的子元素(开关滑块、单选点、勾选图标)需要 pointerEvents: "none",否则它会吃掉父元素的点击。对于 Select 与 Combobox 的行,请改用 item 原语的 asChild prop。详见无样式控件。