---
title: "UniqueID 扩展"
description: "通过 UniqueID 扩展为每个节点添加唯一 ID 并跟踪它们。更多内容请见文档！"
canonical_url: "https://tiptap.zhcndoc.com/editor/extensions/functionality/uniqueid"
---

# UniqueID 扩展

通过 UniqueID 扩展为每个节点添加唯一 ID 并跟踪它们。更多内容请见文档！

`UniqueID` 扩展为你配置的节点类型添加唯一 ID。\
该扩展会跟踪你的节点，即使你拆分它们、合并它们、撤销/重做更改、裁剪内容、粘贴内容……它都能正常工作。\
此外，你可以配置哪些节点类型获得唯一 ID，哪些不获得，且可以自定义这些 ID 的生成方式。

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

## 安装

```bash
npm install @tiptap/extension-unique-id
```

## 设置

### attributeName

附加到 HTML 标签上的属性名称（前缀会是 `data-`）。

默认值：`'id'`

```js
UniqueID.configure({
  attributeName: 'uid',
})
```

### types

所有应获得唯一 ID 的节点类型，例如 `['heading', 'paragraph']`。\
你也可以传入 `'all'`，为文档中除 `doc` 和 `text` 之外的所有节点类型添加 ID。

默认值：`[]`

```js
UniqueID.configure({
  types: ['heading', 'paragraph'],
})
```

```js
UniqueID.configure({
  types: 'all',
})
```

### generateID

用于生成并返回唯一 ID 的函数。该函数接收一个上下文对象（例如 `{ node, pos }`），因此你可以根据节点的类型或其位置自定义 ID 的生成方式。

默认值：`({ node, pos }) => uuidv4()`

```js
UniqueID.configure({
  generateID: ({ node }) => `${node.type.name}-${uuidv4()}`,
})
```

### filterTransaction

忽略某些事务，例如通过协作插件由其他用户应用的事务。

默认值：`null`

```js
import { isChangeOrigin } from '@tiptap/extension-collaboration'

// 添加对协同编辑的支持
UniqueID.configure({
  filterTransaction: (transaction) => !isChangeOrigin(transaction),
})
```

### updateDocument

是否通过为节点添加唯一 ID 来更新文档。如果文档处于只读模式、不可变，或者你不希望它被修改，可以将此属性设置为 `false`。

默认值：`true`

```js
UniqueID.configure({
  updateDocument: false,
})
```

## 与协作（Collaboration）一起使用

> **Important:**
>
> When using the UniqueID extension together with the [Collaboration extension](https://tiptap.zhcndoc.com/editor/extensions/functionality/collaboration.md), ensure that the editor is only mounted **after** the collaboration provider has synced. Mounting the editor on an unsynced `Y.Doc` can lead to unintended document state (e.g., persistent empty paragraphs), which the UniqueID extension will then preserve.

### 不正确的设置

In this example, the editor is mounted immediately with the Collaboration extension before the provider has synced. This causes the editor to initialize against an empty `Y.Doc`, which leads to unintended document mutations.

```tsx
import Collaboration from '@tiptap/extension-collaboration'
import { isChangeOrigin } from '@tiptap/extension-collaboration'
import { EditorContent, useEditor } from '@tiptap/react'
import { TiptapCollabProvider } from '@tiptap-pro/provider'
import { useEffect } from 'react'
import * as Y from 'yjs'

const doc = new Y.Doc()

export default () => {
  // ❌ Editor is mounted before the provider has synced
  const editor = useEditor({
    extensions: [
      // ...other extensions
      UniqueID.configure({
        types: ['paragraph', 'heading'],
        filterTransaction: (transaction) => !isChangeOrigin(transaction),
      }),
      Collaboration.configure({
        document: doc,
      }),
    ],
    content: '<p>Initial content</p>', // This will be duplicated on every sync
  })

  useEffect(() => {
    // Provider connects and syncs after the editor is already mounted
    const provider = new TiptapCollabProvider({
      name: 'your-document-name',
      appId: 'YOUR_APP_ID',
      token: 'YOUR_JWT',
      document: doc,
    })
  }, [])

  return <EditorContent editor={editor} />
}
```

### 正确的设置

To avoid this issue, follow this initialization order:

1. Initialize the `Y.Doc`
2. Start the collaboration provider
3. Wait for the `synced` event
4. Check if the collaborative document is empty
5. Mount the editor with the correct content

```tsx
import Collaboration from '@tiptap/extension-collaboration'
import { isChangeOrigin } from '@tiptap/extension-collaboration'
import { EditorContent, useEditor } from '@tiptap/react'
import { TiptapCollabProvider } from '@tiptap-pro/provider'
import { useEffect } from 'react'
import * as Y from 'yjs'

const doc = new Y.Doc()

export default () => {
  const editor = useEditor({
    extensions: [
      // ...other extensions
      UniqueID.configure({
        types: ['paragraph', 'heading'],
        filterTransaction: (transaction) => !isChangeOrigin(transaction),
      }),
      Collaboration.configure({
        document: doc,
      }),
    ],
    // Do not set content here — wait for sync
  })

  useEffect(() => {
    const provider = new TiptapCollabProvider({
      name: 'your-document-name',
      appId: 'YOUR_APP_ID',
      token: 'YOUR_JWT',
      document: doc,

      onSynced() {
        // Only seed content if the collaborative document is empty
        const isEmpty = doc.getXmlFragment('default').length === 0

        if (isEmpty && editor) {
          editor.commands.setContent(yourInitialContent)
        }
      },
    })
  }, [])

  return <EditorContent editor={editor} />
}
```

### 关键要点

- **不要在同步之前初始化编辑器内容。** 使用协作时不要依赖默认编辑器状态。
- **使用 `filterTransaction`** 来忽略来自协作的变更。查看 [filterTransaction 设置](#filtertransaction)。
- **避免在开发过程中复用损坏的文档名称。** 如果某个错误状态已经被持久化，请使用新的文档名称以干净地开始。

有关完整的协作设置指南，请参考 [安装协作（Install Collaboration）](https://tiptap.zhcndoc.com/collaboration/getting-started/install.md) 文档。

## 服务器端唯一 ID 工具

`generateUniqueIds` 函数允许你在服务端为 Tiptap 文档添加唯一 ID，无需创建 `Editor` 实例。这对于在服务端处理文档或需要为现有内容添加 ID 非常有用。

### 参数

- **`doc`** (`JSONContent`)：要添加唯一 ID 的 Tiptap JSON 文档
- **`extensions`** (`Extensions`)：要使用的扩展列表。必须包含 `UniqueID` 扩展。若要自定义 ID 生成方式，可以向 `UniqueID` 扩展传入选项。

### 返回类型

返回添加了唯一 ID 后的新 Tiptap 文档（一个 `JSONContent` 对象）。

### 示例

```js
import { generateUniqueIds, UniqueID } from '@tiptap/extension-unique-id'
import { StarterKit } from '@tiptap/starter-kit'

const doc = {
  type: 'doc',
  content: [
    { type: 'paragraph', content: [{ type: 'text', text: 'Hello, world!' }] },
    { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: 'My Heading' }] },
  ],
}

const newDoc = generateUniqueIds(doc, [
  StarterKit,
  UniqueID.configure({ types: ['paragraph', 'heading'] }),
])

// 结果：
// {
//   type: 'doc',
//   content: [
//     { type: 'paragraph', content: [{ type: 'text', text: 'Hello, world!' }], attrs: { id: 'd4590f81-52e8-45ec-b317-2e9a805b03e3' } },
//     { type: 'heading', content: [{ type: 'text', text: 'My Heading' }], attrs: { level: 1, id: 'c88f9b5f-7b91-442f-b4d9-ee0d04104827' } }
//   ]
// }
```

该函数会自动获取 `UniqueID` 扩展中的配置，包括 `types`、`attributeName` 和 `generateID` 等选项。
