文档/API

传感器

把输入转换为拖拽的东西——内置的指针和键盘传感器,以及编写自定义传感器的 API。

编辑此页

本页由 AI 翻译,可能存在不准确之处。 阅读英文原文

import { defineSensor, useSensor, pointerSensor, keyboardSensor } from '@vue-dnd-kit/core';
Sensor

通过 Pointer Events 支持鼠标、触摸和触控笔。默认在 sensors 中。

Sensor

Space/Enter、方向键和 Escape(可通过 provider 的 keyboard 选项重新绑定)。默认在 sensors 中;即使设置了 keyboard: false,它也会用 Escape 取消指针拖拽和自定义拖拽。

(sensor: Sensor) => Sensor

定义一个传感器(见 Sensor):它只帮助推导类型,并原样返回参数。

(sensor: Sensor) => void

在上方的 provider 中运行一个传感器,与 provider 的 sensors 并列,持续到调用它的组件(或 effect 作用域)销毁为止。卸载时它的拖拽会被取消。

传感器只说“从这里拖拽这个项”,然后说明它移动到了哪里、是放下了还是被取消了;其余的由 provider 检查(什么可以被拖拽、激活、同一时间只有一次拖拽)。参见传感器与程序化拖拽。

下面是一个小型自定义传感器(用 useSensor 运行),它与 provider 自己的传感器并存,从小地图上拖动棋盘上的棋子。

Live

正在加载演示…

<script setup lang="ts">
import { DnDProvider } from '@vue-dnd-kit/core';
import SensorDesk from './SensorDesk.vue';
</script>

<template>
  <DnDProvider>
    <SensorDesk />
  </DnDProvider>
</template>

Sensor

发起拖拽的输入:指针、键盘,或你自己的输入(游戏手柄、屏幕上的摇杆、语音、脚本驱动的拖拽)。setup 在每个 provider 中运行一次,只在浏览器中运行,位于一个随 provider 结束的副作用作用域中(或者当传感器离开 sensors、或调用 useSensor 的组件卸载时结束)。用 useEventListener 注册监听器,或者返回一个清理函数;届时仍在进行的拖拽会被取消。

要包装一个传感器,用你自己的上下文运行它的 setup。Object.create(context, { activate: { value: … } }) 会保留实时的 getter(status、drag、props):展开运算符会把它们冻结。

string

用于调试。

(context: SensorContext) => void | (() => void)

开始监听输入,每个 provider 一次:想要拖拽时调用 context.activate()。可以返回一个清理函数,在传感器停止时运行。

传感器从它所运行的 provider 中得到的内容。

Readonly<DnDProviderProps>

provider 的 props(例如 activation、keyboard)。在需要时再读取:它们可能会变化。

DnDStatus

provider 的拖拽状态,无论是哪个传感器在执行拖拽。

SensorDrag | null

provider 的拖拽,等待中或拖拽中,无论是哪个传感器发起的;没有拖拽时为 null。传感器之间可以驱动彼此的拖拽:键盘传感器会移动并放下每一次键盘拖拽,例如由“移动”按钮拿起的拖拽(@vue-dnd-kit/actions)。

(activation: SensorActivation) => SensorDrag | null

请求拖拽一个项。provider 会检查:它是否空闲(同一时间只有一次拖拽,放置落位期间也不行)、目标是否是它自己的、未被禁用的可拖拽元素、输入落在哪里(参见 target)以及可拖拽元素的 canDrag,然后等待激活约束并开始拖拽。返回这次拖拽(等待中;或者没有需要等待的条件时,已经在拖拽中),不能开始拖拽时返回 null。

() => void

取消 provider 的拖拽或等待中的激活,无论是哪个传感器在执行它(Escape、隐藏的标签页)。

激活

传感器的输入想要拖拽时,它所请求的内容(SensorContext.activate())。

Element | Key

输入落在哪里:可拖拽元素内部的某个元素,或某个可拖拽元素的 id。元素必须属于这个 provider;对于 'pointer' 拖拽,如果有手柄,它必须位于手柄上,并且不能位于可交互的子元素上(按钮、输入框);对于 'keyboard' 拖拽,它必须是可拖拽元素的焦点目标(手柄,否则是可拖拽元素本身),并且不能是可编辑字段。id 会跳过这些检查:无论输入在哪里,拖拽都从该项开始。

SensorType

拖拽如何移动。'pointer'(默认):它跟随传给 move() 的坐标点,在那里对目标做命中测试,容器在边缘自动滚动,页面显示抓取光标。'keyboard':它像方向键那样通过 step() 和 place() 按项移动,目标会被滚动到视野中而不是自动滚动,结束时焦点回到该项上。Active.sensor 会告诉你是哪一种。

Coordinates

拖拽开始的位置,视口坐标。默认:可拖拽元素的中心。

PointerEvent | KeyboardEvent

输入事件。它会交给可拖拽元素的 canDrag:没有事件时(游戏手柄、程序化拖拽),不会询问 canDrag。pointerType 为 'touch' 时,这次拖拽会成为触摸拖拽(haptics)。

PointerKind | ActivationConstraint

拖拽开始之前等待的条件(在此之前 useDnD().status 为 'activating',并带有进度)。指针类型会先读取可拖拽元素的 activation 选项中对应的设置,然后是 provider 的,最后是默认值(鼠标为 4px,在手柄上立即开始;触控笔为 4px;触摸为 200ms 长按,容差 5px)。约束会按原样使用。默认:无,拖拽立即开始。

(drag: SensorDrag) => void

拖拽已开始,在激活之后:例如捕获指针。

(drag: SensorDrag) => void

拖拽已结束:它的激活被中止,或者它已放下或被取消(无论由谁)。

(drag: SensorDrag) => void

传感器请求的放置没有发生,拖拽继续(onBeforeDrop 返回了 'continue'):move、drop 和 cancel 再次生效。指针传感器会让项跟随指针,直到下一次松开。

按指针类型设置。默认值:鼠标为 { distance: 4 }(在手柄上立即开始),触控笔为 { distance: 4 },触摸为 { delay: 200, tolerance: 5 }。

type ActivationOptions = Partial< Record<PointerKind, ActivationConstraint> >

按下在变成拖拽之前必须满足的条件:移动 distance,或按住 delay,以先满足者为准。都不设置:拖拽立即开始。

number

拖拽开始前指针必须移动的像素数。

number

拖拽开始前指针必须按住的毫秒数。

number

与 delay 一起使用:会中止激活的移动距离(px),这样页面可以滚动。

拖拽

传感器的一次拖拽,从 activate() 开始直到它结束。一旦调用不再适用就会被忽略:开始之前或结束之后的移动、第二次 drop()。

Key

被拖拽项的 id。

SensorType

拖拽的移动方式,即 activate() 所要求的(SensorActivation.type)。

SensorDragState

拖拽所处的阶段:等待激活、拖拽中,或已结束。

boolean

拖拽已经开始过,即使之后已经结束(指针传感器会吞掉拖拽之后的那次点击)。

(point: Coordinates) => void

输入移动了。等待期间检查激活约束(移动超出容差会中止它);拖拽期间,拖拽会移到那里。指针拖拽每帧取一个位置;键盘拖拽会在之前的步进完成后立即移动。

(direction: SensorDirection, options?: SensorStepOptions) => Promise<void>

键盘拖拽:一次方向键步进,与键盘传感器的方向键效果相同(列表中的下一项、'droppables' 模式下下一个接收它的目标,或 keyboard.step 像素)。步进会排队:每一步都等前一步渲染完成后才执行,并且当仍有步进尚未完成时,重复按键(event.repeat)会被跳过。指针拖拽会忽略它。

(position: SortablePosition) => Promise<boolean>

像键盘移动那样,把项放到可排序列表的某个位置(其他列表只有在接收它时才会接纳它),并把拖拽移到它的新位置。没有列表在那里接收它时 resolve 为 false。在键盘拖拽中与 step() 一样排队。

() => Promise<boolean>

放下:如果激活仍在等待中,则改为中止它。在拖拽结束并落位后 resolve:放置成功时为 true,被拒绝(被目标或 onBeforeDrop)或没有东西可放下时为 false。

() => void

取消拖拽(它会飞回原处),或中止等待中的激活。

  • 'pending':等待激活约束;
  • 'dragging':从开始直到放置结果确定或拖拽被取消;
  • 'ended':激活被中止,或者拖拽已放下或被取消,无论是由传感器还是其他原因(Escape、隐藏的标签页、useDnD().cancel()、provider 卸载)。
type SensorDragState = 'pending' | 'dragging' | 'ended'

SensorDrag.step() 的选项。

KeyboardEvent

按键事件,会交给监听器的 getKeyboardCoordinates。默认:该方向键的一个 keydown 事件。

boolean

自由拖拽中更大的步长(与 Shift 相同)。默认:event.shiftKey。

一次键盘步进的方向键。

type SensorDirection = 'up' | 'down' | 'left' | 'right'

可排序列表中的一个位置,用于 SensorDrag.place()(以及 @vue-dnd-kit/actions 的 moveItem)。仅限列表:树通过它们自己的 key 放置项。

Key

列表的 id(SortableListOptions.id)。默认:项当前所在的列表。

number

项最终所在的索引,计算时不包含项本身(多项拖拽的整组只算一次)。被限制在列表范围内;默认:末尾。