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

如何在React Quill或Editor.js中实现类ChatGPT的Typeahead/自动补全?

在React Quill和Editor.js中实现AI驱动的自动补全功能

React Quill 实现方案

React Quill本身无内置这类功能,但可通过自定义逻辑和事件监听实现:

  • 输入事件监听:通过onChange或onTextChange捕获用户输入,当输入长度达到触发阈值(如≥3字符)时,调用OpenAI API获取文本建议。
  • 建议弹窗渲染:在编辑器光标下方显示AI返回的建议内容,提示用户可按Tab键插入。
  • Tab键绑定:监听键盘事件,按下Tab时将建议内容插入当前光标位置,并隐藏弹窗。

示例代码片段:

import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
import { useState, useRef } from 'react';

const AIEnhancedQuill = () => {
  const quillRef = useRef(null);
  const [suggestion, setSuggestion] = useState('');
  const [showSuggestion, setShowSuggestion] = useState(false);

  const handleTextChange = (value, delta, source) => {
    if (source === 'user') {
      const editor = quillRef.current?.getEditor();
      const content = editor.getText().trim();
      if (content.length > 3) {
        // 调用OpenAI API(建议通过后端代理避免密钥暴露)
        fetch('/api/openai/completions', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            model: 'gpt-3.5-turbo-instruct',
            prompt: `继续补充文本:${content}`,
            max_tokens: 100
          })
        })
        .then(res => res.json())
        .then(data => {
          setSuggestion(data.choices[0].text.trim());
          setShowSuggestion(true);
        });
      } else {
        setShowSuggestion(false);
      }
    }
  };

  const handleKeyDown = (e) => {
    if (e.key === 'Tab' && showSuggestion) {
      e.preventDefault();
      const editor = quillRef.current?.getEditor();
      const selection = editor.getSelection();
      editor.insertText(selection.index, suggestion);
      setShowSuggestion(false);
    }
  };

  return (
    <div style={{ position: 'relative' }}>
      <ReactQuill
        ref={quillRef}
        theme="snow"
        onChange={handleTextChange}
        onKeyDown={handleKeyDown}
      />
      {showSuggestion && (
        <div style={{
          position: 'absolute',
          bottom: '100%',
          left: '10px',
          background: '#f5f5f5',
          padding: '8px 12px',
          border: '1px solid #ddd',
          borderRadius: '4px',
          fontSize: '14px'
        }}>
          {suggestion} <span style={{ color: '#666', marginLeft: '8px' }}>按Tab插入</span>
        </div>
      )}
    </div>
  );
};

export default AIEnhancedQuill;

Editor.js 实现方案

Editor.js需通过监听区块输入事件和自定义弹窗实现功能:

  • 区块输入监听:利用Editor.js的input事件监听用户输入,满足触发条件时调用OpenAI API。
  • 建议弹窗管理:在当前编辑区块附近渲染建议弹窗,点击或按Tab键插入内容。
  • 全局键盘监听:捕获Tab键事件,将建议内容插入当前编辑区块。

示例代码片段:

import EditorJS from '@editorjs/editorjs';

let currentSuggestion = '';
let suggestionPopup = null;

const editor = new EditorJS({
  holder: 'editorjs-container',
  tools: {
    paragraph: {
      class: require('@editorjs/paragraph'),
      inlineToolbar: true
    }
  },
  onReady: () => {
    // 监听编辑器输入事件
    editor.listeners.on(editor.ui.nodes.wrapper, 'input', () => {
      const currentBlock = editor.getCurrentBlock();
      const content = currentBlock.getText().trim();
      
      if (content.length > 3) {
        fetch('/api/openai/completions', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            model: 'gpt-3.5-turbo-instruct',
            prompt: `继续补充文本:${content}`,
            max_tokens: 100
          })
        })
        .then(res => res.json())
        .then(data => {
          currentSuggestion = data.choices[0].text.trim();
          renderSuggestionPopup(currentSuggestion, currentBlock);
        });
      } else {
        hideSuggestionPopup();
      }
    });

    // 监听Tab键插入
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Tab' && currentSuggestion) {
        e.preventDefault();
        const currentBlock = editor.getCurrentBlock();
        currentBlock.insertText(currentBlock.getLength(), currentSuggestion);
        hideSuggestionPopup();
      }
    });
  }
});

// 渲染建议弹窗
function renderSuggestionPopup(text, block) {
  hideSuggestionPopup();
  suggestionPopup = document.createElement('div');
  suggestionPopup.style.position = 'absolute';
  suggestionPopup.style.background = '#f5f5f5';
  suggestionPopup.style.padding = '8px 12px';
  suggestionPopup.style.border = '1px solid #ddd';
  suggestionPopup.style.borderRadius = '4px';
  suggestionPopup.style.fontSize = '14px';
  
  const blockRect = block.holder.getBoundingClientRect();
  suggestionPopup.style.top = `${blockRect.bottom + 8}px`;
  suggestionPopup.style.left = `${blockRect.left}px`;
  suggestionPopup.textContent = `${text} 按Tab插入`;
  
  document.body.appendChild(suggestionPopup);
}

// 隐藏建议弹窗
function hideSuggestionPopup() {
  if (suggestionPopup) {
    suggestionPopup.remove();
    suggestionPopup = null;
    currentSuggestion = '';
  }
}

关键优化点

  • API请求防抖:添加300ms左右的输入防抖,避免频繁调用OpenAI API。
  • 密钥安全:禁止在前端代码中直接暴露OpenAI API密钥,通过后端代理处理请求。
  • 光标定位:插入建议后自动将光标移至内容末尾,提升编辑流畅度。

内容的提问来源于stack exchange,提问作者Abdulhakim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 12:15:28