You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React版Tiptap编辑器中添加{{first name}}变量?

在React Tiptap中实现带自定义样式的{{变量}}功能

不用纠结mention插件,直接自定义一个Inline节点扩展就能实现需求,以下是具体步骤:

1. 创建自定义变量节点扩展

创建一个Variable扩展,继承Tiptap的Node类,定义变量的结构、解析规则和渲染方式:

import { Node } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react';
import VariableComponent from './VariableComponent';

export const Variable = Node.create({
  name: 'variable',
  inline: true,
  group: 'inline',
  selectable: true,
  draggable: true,

  addAttributes() {
    return {
      name: {
        default: '',
        parseHTML: element => element.getAttribute('data-name'),
        renderHTML: attributes => ({ 'data-name': attributes.name }),
      },
    };
  },

  parseHTML() {
    return [
      {
        tag: 'span.variable',
      },
    ];
  },

  renderHTML({ node }) {
    return ['span', { class: 'variable', 'data-name': node.attrs.name }, `{{${node.attrs.name}}}`];
  },

  addNodeView() {
    return ReactNodeViewRenderer(VariableComponent);
  },
});

2. 编写变量渲染的React组件

创建VariableComponent.jsx,自定义变量的UI样式,完全匹配你需要的效果:

import React from 'react';
import { NodeViewWrapper } from '@tiptap/react';

const VariableComponent = ({ node, selected }) => {
  return (
    <NodeViewWrapper className={`variable ${selected ? 'selected' : ''}`}>
      <span className="variable__text">{{{node.attrs.name}}}</span>
    </NodeViewWrapper>
  );
};

export default VariableComponent;

3. 添加样式

在CSS文件里定义变量的外观,比如:

.variable {
  background-color: #e8f0fe;
  border-radius: 4px;
  padding: 2px 6px;
  margin: 0 2px;
  font-family: monospace;
  color: #165dff;
  cursor: pointer;
}

.variable.selected {
  outline: 2px solid #165dff;
}

4. 配置并初始化编辑器

在你的React组件中引入自定义扩展,初始化Tiptap编辑器:

import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import { Variable } from './Variable';

const Editor = () => {
  const editor = useEditor({
    extensions: [
      StarterKit,
      Variable,
    ],
    content: '<p>Hello <span class="variable" data-name="first name">{{first name}}</span>!</p>',
  });

  // 定义插入变量的函数
  const insertVariable = (name) => {
    if (!editor) return;
    editor.chain().focus().insertContent(`<span class="variable" data-name="${name}">{{${name}}}</span>`).run();
  };

  return (
    <div>
      <button onClick={() => insertVariable('first name')}>插入{{first name}}</button>
      <button onClick={() => insertVariable('last name')}>插入{{last name}}</button>
      <EditorContent editor={editor} />
    </div>
  );
};

export default Editor;

额外优化:输入触发提示(可选)

如果需要输入{{时弹出变量选择菜单,可以结合@tiptap/suggestion插件实现,核心是定义触发规则和菜单组件:

import { Suggestion } from '@tiptap/suggestion';
import { Variable } from './Variable';

// 配置suggestion
const variableSuggestion = {
  items: ({ query }) => {
    const variables = ['first name', 'last name', 'email', 'phone'];
    return variables.filter(item => item.toLowerCase().includes(query.toLowerCase()));
  },

  render: () => {
    // 自定义菜单渲染逻辑,比如下拉列表
    // 具体实现可以参考Tiptap官方suggestion示例
  },

  command: ({ editor, range, props }) => {
    editor
      .chain()
      .focus()
      .deleteRange(range)
      .insertContentAt(range, `<span class="variable" data-name="${props.item}">{{${props.item}}}</span>`)
      .run();
  },

  allow: ({ state, range }) => {
    const $from = state.doc.resolve(range.from);
    return $from.parent.type.name === 'paragraph';
  },
};

// 在Variable扩展中添加suggestion
export const Variable = Node.create({
  // ... 其他配置
  addProseMirrorPlugins() {
    return [
      Suggestion({
        editor: this.editor,
        ...variableSuggestion,
        trigger: '{{', // 触发字符
      }),
    ];
  },
});

这样就能完全实现你需要的{{变量}}功能,包括自定义UI样式,比用mention插件更贴合需求。

内容的提问来源于stack exchange,提问作者Azim Uddin Ahamed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 03:11:17