---
title: "拖动手柄 React 扩展"
description: "使用 Drag Handle React 扩展启用在基于 React 的 Tiptap 编辑器中拖动节点。请在文档中了解如何设置！"
canonical_url: "https://tiptap.zhcndoc.com/editor/extensions/functionality/drag-handle-react"
---

# 拖动手柄 React 扩展

使用 Drag Handle React 扩展启用在基于 React 的 Tiptap 编辑器中拖动节点。请在文档中了解如何设置！

你是否曾想过在基于 React 的编辑器中拖动节点？我们也有同样的需求——所以这里有一个扩展实现它。

`DragHandleReact` 组件允许你轻松处理编辑器中节点的拖动。你可以定义自定义渲染函数、位置等。
它本质上将 [DragHandle](https://tiptap.zhcndoc.com/editor/extensions/functionality/drag-handle.md) 扩展封装到一个 React 组件中，该组件会自动向编辑器注册和注销扩展。

> **Interactive demo:** [DragHandle](https://embed.tiptap.dev/preview/Extensions/DragHandle/)

## 安装

```bash
npm install @tiptap/extension-drag-handle-react @tiptap/extension-drag-handle @tiptap/extension-node-range @tiptap/extension-collaboration @tiptap/y-tiptap yjs y-protocols
```

## 属性

所有属性遵循与 [DragHandle](https://tiptap.zhcndoc.com/editor/extensions/functionality/drag-handle.md) 扩展相同的结构。

### children

应显示在拖动手柄内部的内容。

```jsx
<DragHandle>
  <div>拖动我！</div>
</DragHandle>
```

### computePositionConfig

拖动手柄的位置计算配置，使用 floating-ui/dom 包。你可以传递在 [floating-ui 文档](https://floating-ui.com/docs/computePosition) 中可用的任何选项。

默认值：`{ placement: 'left-start', strategy: 'absolute' }`

```jsx
<DragHandle
  computePositionConfig={{
    placement: 'left',
    strategy: 'fixed',
  }}
>
  <div>拖动我！</div>
</DragHandle>
```

### onNodeChange

当节点被悬停时返回一个节点或 null。这可以用于高亮当前悬停的节点。

默认值：`undefined`

```jsx
function Component() {
  const [selectedNode, setSelectedNode] = useState(null)

  return (
    <DragHandle
      onNodeChange={({ node, editor, pos }) => {
        setSelectedNode(node)
        // 对节点进行某些操作
      }}
    >
      <div>拖动我！</div>
    </DragHandle>
  )
}
```

### getReferencedVirtualElement

一个返回拖动手柄虚拟元素的函数。当菜单需要相对于特定的 DOM 元素定位时，这很有用。

默认值：`undefined`

```jsx
<DragHandle
  getReferencedVirtualElement={() => {
    // 返回一个用于自定义定位的虚拟元素
    return null
  }}
>
  <div>拖动我！</div>
</DragHandle>
```

### locked

锁定拖动手柄的位置和可见性。如果拖动手柄原本可见，则会保持可见直到解除锁定；如果原本隐藏，则保持隐藏直到解除锁定。

默认值：`false`

```jsx
<DragHandle locked={true}>
  <div>拖动我！</div>
</DragHandle>
```

### pluginKey

在编辑器中存储插件时应使用的键。如果在同一个编辑器中有多个拖动手柄，这非常有用。

默认值：`undefined`

```jsx
<DragHandle pluginKey="myCustomDragHandle">
  <div>拖动我！</div>
</DragHandle>
```

### onElementDragStart

当元素开始被拖动时调用的函数。可以用于添加拖动开始时的自定义逻辑。

```jsx
<DragHandle
  onElementDragStart={(e: DragEvent) => {
    // 拖动开始时执行某些操作
  }}
>
  <div>拖动我！</div>
</DragHandle>
```

### onElementDragEnd

当元素停止被拖动时调用的函数。可以用于添加拖动结束时的自定义逻辑。

```jsx
<DragHandle
  onElementDragEnd={(e: DragEvent) => {
    // 拖动结束时执行某些操作
  }}
>
  <div>拖动我！</div>
</DragHandle>
```

### nested

启用针对嵌套内容（如列表项、引用块及其他嵌套结构）的拖动手柄。

启用后，拖动手柄不仅会出现在顶级块，还会出现在嵌套块。基于规则的评分系统会根据光标位置和配置规则确定目标节点。

默认值：`false`

```jsx
// 使用默认值启用
<DragHandle nested={true}>
  <div>拖动我！</div>
</DragHandle>

// 使用自定义边缘检测启用
<DragHandle nested={{ edgeDetection: { threshold: -16 } }}>
  <div>拖动我！</div>
</DragHandle>
```

#### 带嵌套支持的完整示例

```jsx
import DragHandle from '@tiptap/extension-drag-handle-react'
import { EditorContent, useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
import { useState } from 'react'

const NESTED_CONFIG = { edgeDetection: { threshold: -16 } }

export default function Editor() {
  const [nested, setNested] = useState(true)

  const editor = useEditor({
    extensions: [StarterKit],
    content: '<ul><li>Item 1</li><li>Item 2</li></ul>',
  })

  return (
    <>
      <button onClick={() => setNested(!nested)}>
        切换嵌套
      </button>
      <DragHandle editor={editor} nested={nested ? NESTED_CONFIG : false}>
        <div className="drag-handle" />
      </DragHandle>
      <EditorContent editor={editor} />
    </>
  )
}
```

> **性能提示:**
>
> 当使用 React 状态切换 `nested` 属性时，请将配置对象定义为组件外部的常量，避免不必要的重新渲染。

请参见 [DragHandle 嵌套文档](https://tiptap.zhcndoc.com/editor/extensions/functionality/drag-handle.md#nested-drag-handle) 获取包括边缘检测、自定义规则及允许容器等详细配置选项。

### 命令

请参见 [DragHandle](https://tiptap.zhcndoc.com/editor/extensions/functionality/drag-handle.md) 扩展以获取可用的编辑器命令。
