Skip to content

useDrag

一个拖拽操作管理 Hook,提供完整的拖拽功能,支持位置约束、网格对齐、轴限制等高级特性。自动处理鼠标事件和拖拽状态管理。

基础用法

🎯 基础拖拽

拖我
位置: (0, 0)
拖拽中: false

约束拖拽示例

🔒 约束拖拽

边界约束

📦

水平拖拽

↔️

网格对齐

🎯

API 参考

参数

参数类型默认值说明
optionsUseDragOptions{}配置选项

UseDragOptions

属性类型默认值说明
initialPositionPosition{ x: 0, y: 0 }初始位置
axis'x' | 'y' | 'both''both'拖拽轴限制
grid[number, number]-网格对齐,[x间距, y间距]
boundaryBoundary-拖拽边界限制
constrainToParentbooleanfalse是否约束在父元素内
handlestring-拖拽手柄选择器
disabledbooleanfalse是否禁用拖拽
onDragStart(state: DragState, event: MouseEvent) => void-拖拽开始回调
onDrag(state: DragState, event: MouseEvent) => void-拖拽中回调
onDragEnd(state: DragState, event: MouseEvent) => void-拖拽结束回调

返回值

useDrag 返回一个数组,包含以下元素:

typescript
const [elementRef, dragState, startDrag, stopDrag, resetPosition, setPosition] = useDrag(options);
索引名称类型说明
0elementRefRef<HTMLElement | null>拖拽元素的引用
1dragStateComputedRef<DragState>拖拽状态
2startDrag(event: MouseEvent) => void手动开始拖拽
3stopDrag() => void手动停止拖拽
4resetPosition() => void重置位置
5setPosition(x: number, y: number) => void设置位置

类型定义

typescript
export interface Position {
  x: number;
  y: number;
}

export interface Boundary {
  left?: number;
  top?: number;
  right?: number;
  bottom?: number;
}

export interface DragState {
  position: Position;
  isDragging: boolean;
  startPosition: Position;
  offset: Position;
}

export interface UseDragOptions {
  initialPosition?: Position;
  axis?: "x" | "y" | "both";
  grid?: [number, number];
  boundary?: Boundary;
  constrainToParent?: boolean;
  handle?: string;
  disabled?: boolean;
  onDragStart?: (state: DragState, event: MouseEvent) => void;
  onDrag?: (state: DragState, event: MouseEvent) => void;
  onDragEnd?: (state: DragState, event: MouseEvent) => void;
}

export type UseDragReturn = [
  Ref<HTMLElement | null>,
  ComputedRef<DragState>,
  (event: MouseEvent) => void,
  () => void,
  () => void,
  (x: number, y: number) => void,
];

使用场景

  1. 拖拽排序 - 列表项的拖拽排序
  2. 画布操作 - 图形编辑器中的元素拖拽
  3. 布局调整 - 可拖拽的面板和窗口
  4. 游戏开发 - 游戏中的拖拽交互
  5. 数据可视化 - 图表中的拖拽操作

高级用法

拖拽手柄

typescript
const [dragRef, dragState] = useDrag({
  handle: ".drag-handle", // 只有 .drag-handle 元素可以拖拽
});

约束到父元素

typescript
const [dragRef, dragState] = useDrag({
  constrainToParent: true, // 自动约束在父元素内
});

回调函数

typescript
const [dragRef, dragState] = useDrag({
  onDragStart: (state, event) => {
    console.log("开始拖拽", state.position);
  },
  onDrag: (state, event) => {
    console.log("拖拽中", state.position);
  },
  onDragEnd: (state, event) => {
    console.log("拖拽结束", state.position);
  },
});

注意事项

  1. 需要将 elementRef 绑定到要拖拽的元素上
  2. 拖拽元素需要设置 position: absoluteposition: relative
  3. 使用 transform 来应用位置变化以获得更好的性能
  4. 网格对齐会自动调整位置到最近的网格点
  5. 边界约束会限制拖拽范围
  6. 组件卸载时会自动清理事件监听器

基于 MIT 协议发布