---
title: "Node API"
description: "为你的 Tiptap 编辑器创建一个新节点，从零开始创造独特的编辑体验。了解更多内容请参考文档！"
canonical_url: "https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/create-new/node"
---

# Node API

为你的 Tiptap 编辑器创建一个新节点，从零开始创造独特的编辑体验。了解更多内容请参考文档！

Tiptap 的强大之处在于它的灵活性。你可以从零开始创建自己的扩展，构建量身定制的独特编辑体验。

## 创建一个节点

节点是你编辑器的基本构建块。它们可以是块节点或行内节点。好的学习实例包括 [`Paragraph`](https://tiptap.zhcndoc.com/editor/extensions/nodes/paragraph.md)、[`Heading`](https://tiptap.zhcndoc.com/editor/extensions/nodes/heading.md) 或 [`CodeBlock`](https://tiptap.zhcndoc.com/editor/extensions/nodes/code-block.md)。

它们扩展了 [扩展 API](https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/extension.md) 的所有选项和方法，并添加了一些特定于节点的选项。

让我们添加一个简单的节点扩展，看看它是如何工作的。

```typescript
import { Node } from '@tiptap/core'

const CustomNode = Node.create({
  name: 'customNode',

  addOptions() {
    return {
      HTMLAttributes: {},
    }
  },

  parseHTML() {
    return [
      {
        tag: 'div',
      },
    ]
  },

  renderHTML({ HTMLAttributes }) {
    return ['div', HTMLAttributes, 0]
  },
})
```

你也可以使用回调函数来创建节点。如果你想封装扩展的逻辑，比如定义事件处理程序或其他自定义逻辑，这非常有用。

```js
import { Node } from '@tiptap/core'

const CustomNode = Node.create(() => {
  // 你可以在这里定义变量或函数，用于你的架构定义
  const customVariable = 'foo'

  function onCreate() {}
  function onUpdate() {}

  return {
    name: 'customNode',
    onCreate,
    onUpdate,

    // 你的代码写在这里。
  }
})
```

这段代码创建了一个名为 `CustomNode` 的新节点扩展。它添加了一个 `addOptions` 方法来定义节点的选项，这些选项可由用户配置。同时它还添加了 `parseHTML` 和 `renderHTML` 方法，定义节点如何解析和渲染为 HTML。

安装到编辑器时，与其他扩展一样，将其添加到 `extensions` 数组中。

```typescript
import { Editor } from '@tiptap/core'

new Editor({
  extensions: [CustomNode],
})

// 或者如果使用 React 或 Vue

const editor = useEditor({
  extensions: [CustomNode],
})
```

现在让我们仔细看看可用于节点的选项和方法。

## 节点选项

创建一个节点时，可以定义可由用户配置的选项。这些选项可用于自定义节点的行为或外观。

### `parseHTML`

`parseHTML` 方法用于定义如何从 HTML 中解析标记。它应该返回一个数组，表示标记的属性。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.MarkSpec.parseDOM) 中的 `parseDOM` 属性。

```typescript
const CustomMark = Mark.create({
  name: 'customMark',

  parseHTML() {
    return [
      {
        tag: 'span',
        getAttrs: (node) => {
          return {
            class: node.getAttribute('class'),
          }
        },
      },
    ]
  },
})
```

这将在粘贴事件期间用于将 HTML 内容解析为标记。

### `renderHTML`

`renderHTML` 方法用于定义如何将标记渲染为 HTML。它应该返回一个表示标记 HTML 表示的数组。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.MarkSpec.toDOM) 中的 `toDOM` 属性。

```typescript
const CustomMark = Mark.create({
  name: 'customMark',

  renderHTML({ HTMLAttributes }) {
    return ['span', HTMLAttributes, 0]
  },
})
```

这将在复制事件期间用于将标记渲染为 HTML。更多细节请参见 [扩展现有扩展](https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/extend-existing.md#render-html) 指南。

### `addAttributes`

`addAttributes` 方法用于定义标记的自定义属性。它应该返回一个包含属性名称及其默认值的对象。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.MarkSpec.attrs) 中的 `attrs` 属性。

```typescript
const CustomMark = Mark.create({
  name: 'customMark',

  addAttributes() {
    return {
      customAttribute: {
        default: 'value',
        parseHTML: (element) => element.getAttribute('data-custom-attribute'),
      },
    }
  },
})
```

有关更多细节，请参见 [扩展现有扩展](https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/extend-existing.md#attributes) 指南。

### `topNode`

定义此节点是否应为顶级节点（文档）。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.topNode) 中的 `topNode` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  topNode: true,
})
```

### `content`

该节点的内容表达式，如 [架构指南](https://tiptap.zhcndoc.com/docs/guide/.md#schema.content_expressions) 所述。如果未给定，则该节点不允许任何内容。

你可以在 Prosemirror 文档中阅读更多内容 [这里](https://prosemirror.net/docs/guide/#schema.content_expressions)。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  content: 'block+',
})
```

### `marks`

该节点内允许的标记。可以是指向标记名称或组的空格分隔字符串，`"_"` 明确允许所有标记，或 `""` 禁止标记。如果未给定，具有行内内容的节点默认允许所有标记，其他节点默认不允许标记。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.marks) 中的 `marks` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  marks: 'strong em',
})
```

### `group`

该节点所属的组或用空格分隔的组，可以在架构的内容表达式中引用。

默认情况下，Tiptap 将 `block` 和 `inline` 作为节点的组。如果你想将特定节点分组并在架构中处理它们，也可以使用自定义组。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.group) 中的 `group` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  group: 'block',
})
```

### `inline`

此属性应该设置为 true ，以表示行内节点。（对文本节点是隐含的）。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.inline) 中的 `inline` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  inline: true,
})
```

### `atom`

可以设置为 true，以指示虽然这不是一个 [叶节点](https://prosemirror.net/docs/ref/#model.NodeType.isLeaf)，但它没有直接可编辑的内容，应视为视图中的一个单元。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.atom) 中的 `atom` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  atom: true,
})
```

### `selectable`

控制该类型的节点是否可以被选中作为 [节点选择](https://prosemirror.net/docs/ref/#state.NodeSelection)。默认情况下，对于非文本节点为 true。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.selectable) 中的 `selectable` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  selectable: false,
})
```

### `draggable`

确定该类型的节点是否可以在不被选中的情况下拖动。默认值为 false。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.draggable) 中的 `draggable` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  draggable: true,
})
```

### `code`

可以用于指示此节点包含代码，这会导致某些命令表现得不同。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.code) 中的 `code` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  code: true,
})
```

### `whitespace`

控制该节点中空格的解析方式。默认值为 `"normal"`，这会导致 [DOM 解析器](https://prosemirror.net/docs/ref/#model.DOMParser) 在正常模式下折叠空格，其他情况则标准化（用空格替换换行等）。`"pre"` 则使解析器保留节点内的空格。如果未给定此选项，但 [`code`](https://prosemirror.net/docs/ref/#model.NodeSpec.code) 为 true，则 `whitespace` 默认值为 `"pre"`。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.whitespace) 中的 `whitespace` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  whitespace: 'pre',
})
```

### `linebreakReplacement`

允许将 **单个** 节点设置为换行等价物（例如 hardBreak）。在转换具有空格设置为 "pre" 并且不支持换行节点（例如 codeBlock）与支持换行节点的其他块类型（例如段落）之间进行转换时，将使用此节点作为换行，而不是删除换行符。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.linebreakReplacement) 中的 `linebreakReplacement` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  linebreakReplacement: true,
})
```

### `defining`

启用时，同时启用 [`definingAsContext`](https://prosemirror.net/docs/ref/#model.NodeSpec.definingAsContext) 和 [`definingForContent`](https://prosemirror.net/docs/ref/#model.NodeSpec.definingForContent)。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.defining) 中的 `defining` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  defining: true,
})
```

### `isolating`

启用时（默认值为 false），该类型节点的两侧视为边界，常规编辑操作（如退格或提升）不会穿越。一个应该启用此功能的节点示例是表格单元。

将映射到 [ProseMirror 架构](https://prosemirror.net/docs/ref/#model.NodeSpec.isolating) 中的 `isolating` 属性。

```typescript
const CustomNode = Node.create({
  name: 'customNode',

  isolating: true,
})
```

### `addNodeView`（高级）

对于高级用例，比如需要在节点内部执行 JavaScript，例如渲染一个围绕图像的复杂界面，你需要了解节点视图。

它们非常强大，但也很复杂。简单来说，你需要返回一个父 DOM 元素和一个内容应该渲染到的 DOM 元素。查看以下简化示例：

```js
import Image from '@tiptap/extension-image'

const CustomImage = Image.extend({
  addNodeView() {
    return () => {
      const container = document.createElement('div')

      container.addEventListener('click', (event) => {
        alert('点击了容器')
      })

      const content = document.createElement('div')
      container.append(content)

      return {
        dom: container,
        contentDOM: content,
      }
    }
  },
})
```

关于节点视图有很多内容需要学习，因此请前往我们指南中关于节点视图的 [专门部分](https://tiptap.zhcndoc.com/editor/extensions/custom-extensions/node-views.md) 获取更多信息。如果你正在寻找一个实际的例子，查看 [`TaskItem`](https://tiptap.zhcndoc.com/editor/extensions/nodes/task-item.md) 节点的源代码。这个节点使用节点视图来渲染复选框。
