首页
/ 超简单集成!Tiptap提及功能实现@用户与标签的完整指南

超简单集成!Tiptap提及功能实现@用户与标签的完整指南

2026-02-05 05:51:44作者:侯霆垣

你是否还在为编辑器中的@提及功能开发而烦恼?从用户列表加载到实时搜索,再到样式自定义,整个流程涉及太多细节。本文将带你一文掌握Tiptap编辑器的提及功能实现,无需复杂配置,零基础也能快速上手。读完本文你将获得:

  • 3分钟完成@用户功能集成的具体步骤
  • 同时支持@用户和#标签的多触发配置方案
  • 企业级样式定制与性能优化技巧
  • 完整可复用的Vue组件代码示例

核心实现原理

Tiptap的提及功能由extension-mention模块提供,基于ProseMirror的Suggestion插件实现触发式交互。其核心工作流程如下:

sequenceDiagram
    participant 用户
    participant 编辑器
    participant 提及插件
    participant 数据源
    
    用户->>编辑器: 输入"@"字符
    编辑器->>提及插件: 触发建议事件
    提及插件->>数据源: 请求匹配列表
    数据源-->>提及插件: 返回用户/标签数据
    提及插件-->>编辑器: 渲染下拉选项
    用户->>编辑器: 选择列表项
    编辑器->>提及插件: 创建提及节点
    提及插件-->>编辑器: 插入格式化的提及标签

该模块支持多触发字符配置(如@和#),通过suggestions选项可分别定义用户提及和标签提及的行为。核心实现代码位于mention.ts,主要包含:

  • MentionNodeAttrs接口定义数据属性(id/label/trigger字符)
  • renderText/renderHTML控制渲染逻辑
  • addProseMirrorPlugins注册建议插件

基础集成步骤

以Vue项目为例,通过以下三步即可实现基础@提及功能:

1. 安装依赖

npm install @tiptap/core @tiptap/extension-mention @tiptap/vue-3

2. 配置提及扩展

创建基础编辑器实例,配置Mention扩展:

<template>
  <editor-content :editor="editor" />
</template>

<script>
import { Editor, EditorContent } from '@tiptap/vue-3'
import Document from '@tiptap/extension-document'
import Paragraph from '@tiptap/extension-paragraph'
import Text from '@tiptap/extension-text'
import Mention from '@tiptap/extension-mention'

export default {
  components: { EditorContent },
  data() {
    return { editor: null }
  },
  mounted() {
    this.editor = new Editor({
      extensions: [
        Document,
        Paragraph,
        Text,
        Mention.configure({
          HTMLAttributes: { class: 'mention' },
          suggestion: {
            char: '@',
            items: ({ query }) => {
              // 模拟用户数据
              const users = [
                { id: '1', label: '张三' },
                { id: '2', label: '李四' },
                { id: '3', label: '王五' }
              ]
              return users
                .filter(user => user.label.toLowerCase().includes(query.toLowerCase()))
                .slice(0, 5)
            },
          }
        })
      ],
      content: '<p>开始输入@触发提及...</p>'
    })
  }
}
</script>

3. 添加样式

为提及标签添加视觉样式:

.mention {
  background-color: #e5f3ff;
  border-radius: 4px;
  padding: 0 2px;
  color: #1a73e8;
  font-weight: 500;
}

高级功能实现

多类型提及配置

通过suggestions选项可同时支持@用户和#标签:

Mention.configure({
  suggestions: [
    {
      char: '@',
      pluginKey: 'user-mention',
      items: ({ query }) => fetchUsers(query),
      command: ({ editor, range, props }) => {
        editor
          .chain()
          .focus()
          .insertContentAt(range, [
            {
              type: 'mention',
              attrs: {
                id: props.id,
                label: props.label,
                mentionSuggestionChar: '@'
              }
            },
            { type: 'text', text: ' ' }
          ])
          .run()
      }
    },
    {
      char: '#',
      pluginKey: 'tag-mention',
      items: ({ query }) => fetchTags(query),
      // 标签专用命令...
    }
  ]
})

自定义建议UI

创建自定义建议组件替代默认下拉框,示例实现见demos/src/Nodes/Mention/Vue/index.vue

<template>
  <div v-if="editor">
    <editor-content :editor="editor" />
    <div v-if="showSuggestions" class="suggestion-menu">
      <div 
        v-for="item in items" 
        :key="item.id"
        @click="selectItem(item)"
      >
        {{ item.label }}
      </div>
    </div>
  </div>
</template>

样式定制与优化

推荐样式方案

参考官方演示的样式配置Nodes/Mention/Vue/index.vue

.tiptap {
  .mention {
    background-color: var(--purple-light);
    border-radius: 0.4rem;
    box-decoration-break: clone;
    color: var(--purple);
    padding: 0.1rem 0.3rem;
    
    &:hover {
      background-color: var(--purple-lighter);
    }
  }
}

性能优化建议

  1. 防抖查询:在suggestion.items中添加防抖处理
  2. 缓存结果:对相同查询词的结果进行缓存
  3. 虚拟滚动:长列表时使用vue-virtual-scroller优化渲染
// 防抖示例
items: debounce(({ query }) => fetchUsers(query), 300)

完整示例代码

查看Nodes/Mention/Vue/index.vue获取完整演示代码,该示例包含:

  • 基础提及功能实现
  • 样式美化
  • 模拟数据加载
  • 多用户提及演示

核心配置部分:

Mention.configure({
  HTMLAttributes: { class: 'mention' },
  suggestion: {
    items: ({ query }) => {
      return [
        { id: '1', label: 'Jennifer Grey' },
        { id: '2', label: 'Winona Ryder' },
        { id: '3', label: 'Axl Rose' },
        { id: '4', label: 'Christina Applegate' }
      ].filter(item => 
        item.label.toLowerCase().includes(query.toLowerCase())
      )
    },
    render: () => { /* 自定义渲染逻辑 */ }
  }
})

常见问题解决

1. 提及节点无法删除

检查deleteTriggerWithBackspace配置,设为true允许删除触发字符:

Mention.configure({
  deleteTriggerWithBackspace: true
})

2. 多触发字符冲突

确保不同触发类型使用不同的pluginKey

suggestions: [
  { char: '@', pluginKey: 'user-mention' },
  { char: '#', pluginKey: 'tag-mention' }
]

3. 样式不生效

确认CSS选择器与HTMLAttributes中定义的class匹配,参考官方样式示例

总结与扩展

Tiptap的提及功能通过灵活的配置选项和可扩展的插件系统,提供了企业级的@提及与标签功能实现。通过本文介绍的方法,你可以快速集成基础功能,并根据需求扩展为支持多类型、自定义UI、性能优化的完整解决方案。

更多高级用法可参考:

通过组合使用extension-mention与其他扩展,如extension-link,可实现更复杂的交互效果,为你的编辑器添加强大的协作能力。

登录后查看全文
热门项目推荐
相关项目推荐