---
title: "如何开发自定义菜单"
description: "了解如何在 Tiptap 编辑器中开发自定义气泡或浮动菜单。更多内容请阅读我们的文档！"
canonical_url: "https://tiptap.zhcndoc.com/editor/getting-started/style-editor/custom-menus"
---

# 如何开发自定义菜单

了解如何在 Tiptap 编辑器中开发自定义气泡或浮动菜单。更多内容请阅读我们的文档！

Tiptap 的初始状态非常原始，但这也是一件好事。您可以完全控制编辑器的外观。

当我们说完全控制时，我们是认真的。您可以（也必须）自己构建一个菜单，尽管 Tiptap 会帮助您连接一切。

## 菜单

编辑器提供了一个流畅的 API 来触发命令并添加活动状态。您可以使用任何您喜欢的标记。为简化菜单定位，Tiptap 提供了一些实用工具和组件。让我们逐个了解最典型的用例。

### 固定菜单

固定菜单是一个永久固定在某个位置的菜单。例如，将固定菜单放在编辑器上方非常常见。Tiptap 并不自带固定菜单，但您可以通过创建一个 `<div>` 元素并在其中填充 `<button>` 元素来构建一个。[见下文](#buttons) 了解这些按钮如何触发编辑器中的 [命令](https://tiptap.zhcndoc.com/editor/api/commands.md)，例如加粗或斜体文本。

### 气泡菜单

[气泡菜单](https://tiptap.zhcndoc.com/editor/extensions/functionality/bubble-menu.md) 是在选择文本时出现的菜单。标记和样式完全由您决定。

> **Interactive demo:** [BubbleMenu](https://embed.tiptap.dev/preview/Extensions/BubbleMenu?inline=false\&hideSource=true)

### 浮动菜单

[浮动菜单](https://tiptap.zhcndoc.com/editor/extensions/functionality/floatingmenu.md) 是在您将光标放在空行时出现在编辑器中的菜单。同样，标记和样式完全由您决定。

> **Interactive demo:** [FloatingMenu](https://embed.tiptap.dev/preview/Extensions/FloatingMenu?inline=false\&hideSource=true)

### 斜杠命令（进行中）

虽然尚未有正式的扩展，但有一个 [实验](https://tiptap.zhcndoc.com/examples/experiments/slash-commands.md) 允许您使用“斜杠命令”。通过斜杠命令，在新行开头输入 `/` 会显示一个弹出菜单。

## 按钮

好的，您已经有了菜单。但是如何连接这些功能呢？

### 命令

您已经让编辑器运行并希望添加第一个按钮。您需要一个带有点击处理程序的 `<button>` HTML 标签。根据您的设置，这可能看起来像以下示例：

```html
<button onclick="editor.chain().focus().toggleBold().run()">加粗</button>
```

哦，这个命令很长，对吧？实际上，这是一个 [命令链](https://tiptap.zhcndoc.com/editor/api/commands.md)。我们逐个了解一下：

```js
editor.chain().focus().toggleBold().run()
```

1. `editor` 应该是一个 Tiptap 实例，
2. `chain()` 用于告诉编辑器您想执行多个命令，
3. `focus()` 将焦点重新设置到编辑器上，
4. `toggleBold()` 将选定的文本加粗。如果文本已经是加粗状态，则取消加粗。
5. `run()` 将执行这一连串命令。

换句话说：这将是您文本编辑器的一个典型 **加粗** 按钮。

可用命令取决于注册到编辑器的扩展。大多数扩展都带有 `set…()`、`unset…()` 和 `toggle…()` 命令。请查看扩展文档以了解实际可用的内容，或直接在代码编辑器的自动补全中浏览。

### 保持焦点

您在上面的示例中已经看到 `focus()` 命令。当您点击按钮时，浏览器将焦点放到该 DOM 元素上，编辑器便失去了焦点。您可能想要将 `focus()` 添加到所有菜单按钮，这样用户的写作流程就不会被打断。

### 活动状态

编辑器提供了一个 `isActive()` 方法来检查某些内容是否已应用于所选文本。在 Vue.js 中，您可以利用该函数切换 CSS 类：

**Important**: If you are using React, values from the editor state are not automatically reactive to avoid performance issues,
that means the `isActive()` value will always return the value of the initial editor state.
To subscribe to the editor state you can use the `useEditorState` hook as described [here](https://tiptap.zhcndoc.com/editor/getting-started/install/react.md#reacting-to-editor-state-changes).

```html
<button
  :class="{ 'is-active': editor.isActive('bold') }"
  @click="editor.chain().focus().toggleBold().run()"
>
  加粗
</button>
```

这会为节点和标记切换 `.is-active` 类。您甚至可以检查特定的属性。以下是一个忽略不同属性的 [`Highlight`](https://tiptap.zhcndoc.com/editor/extensions/marks/highlight.md) 标记示例：

```js
editor.isActive('highlight')
```

还有一个比较给定属性的示例：

```js
editor.isActive('highlight', { color: '#ffa8a8' })
```

甚至支持正则表达式：

```js
editor.isActive('textStyle', { color: /.*/ })
```

您甚至可以检查节点和标记，但仅检查属性。以下是使用 [`TextAlign`](https://tiptap.zhcndoc.com/editor/extensions/functionality/textalign.md) 扩展的示例：

```js
editor.isActive({ textAlign: 'right' })
```

如果您的选择跨越多个节点或标记，或选择的仅部分有标记，则 `isActive()` 将返回 `false`，表示没有活动状态。这种行为是故意的，因为它允许用户立即将新的节点或标记应用于所选内容。

## 用户体验

在设计良好的用户体验时，您需要考虑几个方面。

### 可访问性

- 确保用户可以使用键盘导航菜单
- 使用 [title 属性](https://developer.mozilla.org/de/docs/Web/HTML/Global_attributes/title)
- 使用 [ARIA 属性](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics)
- 列出可用的键盘快捷键

### 图标

大多数编辑器菜单为其按钮使用图标。在我们的一些演示中，我们使用了开源图标集 [Remix Icon](https://remixicon.com/)。但是，您可以使用任何您喜欢的图标集。以下是一些建议：

- [Remix Icon](https://remixicon.com/#editor)
- [Font Awesome](https://fontawesome.com/icons?c=editors)
- [UI icons](https://www.ibm.com/design/language/iconography/ui-icons/library/)
