提及扩展

版本下载量

老实说,提及节点简直太棒了。它支持 @提及,例如可以提醒用户,并提供完全的渲染控制。

几乎所有内容都可以自定义。您可以传递自定义组件进行渲染。所有示例使用 .filter() 搜索项目,但您可以自由发送异步查询到 API 或将更高级的库添加到您的项目中,例如 fuse.js

安装

npm install @tiptap/extension-mention

依赖

为了正确放置弹出框,我们在所有示例中使用 tippy.js。您可以自由选择自己喜欢的库,但如果您愿意,可以直接安装我们使用的库:

npm install tippy.js

自 2.0.0-beta.193 版本起,我们将 @tiptap/suggestion 标记为一个同伴依赖。这意味着,您需要手动安装它。

npm install @tiptap/suggestion

设置

HTMLAttributes

应添加到渲染的 HTML 标签的自定义 HTML 属性。

Mention.configure({
  HTMLAttributes: {
    class: 'my-custom-class',
  },
})

renderText

定义提及文本应如何渲染。

Mention.configure({
  renderText({ options, node }) {
    return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`
  },
})

renderHTML

定义提及 HTML 元素应如何渲染,如果您想渲染的元素不是 span(例如 a),这非常有用。

Mention.configure({
  renderHTML({ options, node }) {
    return [
      'a',
      mergeAttributes({ href: '/profile/1' }, options.HTMLAttributes),
      `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`,
    ]
  },
})

deleteTriggerWithBackspace

切换是否在删除提及节点时也删除建议字符。默认值为 false

Mention.configure({
  deleteTriggerWithBackspace: true,
})

suggestion

建议工具的选项。用于定义什么字符触发建议弹出框,以及其他参数。了解更多

Mention.configure({
  suggestion: {
    // …
  },
})

suggestions

允许您在同一编辑器中定义多种类型的提及。例如,使用 @ 触发器为人定义提及,并使用 # 触发器为电影定义提及。阅读更多关于建议工具的内容

Mention.configure({
  suggestions: [
    {
      char: '@',
      // 建议工具的其他选项
    },
    {
      char: '#',
      // 建议工具的其他选项
    },
  ],
})

以下是一个示例演示:

协作

使用 Tiptap 协作功能时,当有人输入提及时,有时建议弹窗会“弹出”给远程用户。为了防止这种情况,您可以配置 shouldShow 选项:

import { Mention } from '@tiptap/extension-mention'
import { isChangeOrigin } from '@tiptap/extension-collaboration'

const Editor = new Editor({
  extensions: [
    Mention.configure({
      suggestion: {
        shouldShow: ({ transaction }) => isChangeOrigin(transaction),
      },
    }),
  ],
})

这样可以确保建议菜单只对实际输入触发字符的用户打开。

使用原生 JavaScript

下面是一个完整示例,展示了如何设置带有建议列表的提及功能:

import { Editor } from '@tiptap/core'
import Mention from '@tiptap/extension-mention'

new Editor({
  element: document.querySelector('#editor'),
  extensions: [
    StarterKit,
    Mention.configure({
      HTMLAttributes: {
        class: 'mention',
      },
      suggestion: {
        char: '@',
        items: ({ query }) => {
          return ['Alice', 'Bob', 'Carol'].filter((name) =>
            name.toLowerCase().includes(query.toLowerCase())
          )
        },
        render: () => {
          let popup

          return {
            onStart: (props) => {
              popup = document.createElement('div')
              popup.classList.add('suggestion-popup')
              props.items.forEach((item) => {
                const button = document.createElement('button')
                button.textContent = item
                button.addEventListener('click', () => props.command({ id: item }))
                popup.appendChild(button)
              })
              document.body.appendChild(popup)
            },
            onUpdate: (props) => {
              popup.innerHTML = ''
              props.items.forEach((item) => {
                const button = document.createElement('button')
                button.textContent = item
                button.addEventListener('click', () => props.command({ id: item }))
                popup.appendChild(button)
              })
            },
            onExit: () => {
              popup?.remove()
            },
          }
        },
      },
    }),
  ],
  content: '<p>输入 @ 来提及某人。</p>',
})

您也可以传入自定义的 React 或 Vue 组件进行渲染。有关详细信息,请参阅 Suggestion utility

源代码

packages/extension-mention/