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

React项目中如何用Debounce获取Lexical编辑器的JSON状态与文本内容

实现Lexical编辑器状态防抖同步到服务器(React 18 + Lexical 0.3.8)

1. 确认依赖安装

先确保安装指定版本的依赖:

npm install react@^18.2.0 lexical@^0.3.8 @lexical/react@^0.3.8
# 或使用yarn
yarn add react@^18.2.0 lexical@^0.3.8 @lexical/react@^0.3.8

2. 实现防抖函数

可以自定义轻量防抖函数,也可使用lodash.debounce,以下是自定义实现:

function debounce(func, delay) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

3. 构建带防抖同步的编辑器组件

核心是通过OnChangePlugin监听编辑器变化,提取JSON状态与纯文本后,通过防抖函数批量发送至服务器:

import React, { useCallback } from 'react';
import { LexicalComposer } from '@lexical/react/LexicalComposer';
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
import { createEditor } from 'lexical';
import { $getRoot } from 'lexical';

// 防抖函数
function debounce(func, delay) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

// 发送数据到服务器的API
const sendEditorData = async (stateJson, plainText) => {
  try {
    await fetch('/api/save-editor-data', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ state: stateJson, text: plainText }),
    });
  } catch (err) {
    console.error('保存编辑器数据失败:', err);
  }
};

// 防抖后的发送函数,设置500ms延迟可按需调整
const debouncedSend = debounce(sendEditorData, 500);

const DebouncedLexicalEditor = () => {
  const initialConfig = {
    namespace: 'MySyncEditor',
    theme: {}, // 可自定义编辑器主题样式
    onError: (err) => console.error(err),
  };

  // 处理编辑器变化的回调
  const handleChange = useCallback((editorState) => {
    // 获取JSON格式的完整编辑器状态
    const stateJson = editorState.toJSON();
    
    // 获取纯文本内容(必须在read回调内执行Lexical DOM操作)
    let plainText = '';
    editorState.read(() => {
      const root = $getRoot();
      plainText = root.getTextContent();
    });

    // 触发防抖发送
    debouncedSend(stateJson, plainText);
  }, []);

  return (
    <LexicalComposer initialConfig={initialConfig}>
      <RichTextPlugin
        contentEditable={<ContentEditable />}
        placeholder={<div>开始输入内容...</div>}
      />
      <HistoryPlugin />
      {/* 监听编辑器变化 */}
      <OnChangePlugin onChange={handleChange} />
    </LexicalComposer>
  );
};

export default DebouncedLexicalEditor;

关键细节说明

  • JSON状态获取:通过editorState.toJSON()直接拿到包含所有节点、格式的完整编辑器状态,可用于后续恢复编辑器内容。
  • 纯文本提取:借助editorState.read()回调与$getRoot().getTextContent()获取纯文本,这是Lexical官方推荐的读取DOM状态的方式,避免状态不一致问题。
  • 防抖控制:将请求逻辑包裹在防抖函数中,减少频繁输入时的服务器请求次数,500ms延迟可根据业务需求调整。
  • 版本适配:代码基于lexical@0.3.8与@lexical/react@0.3.8编写,确保OnChangePlugin等API调用符合版本要求。

若需手动触发状态获取,可通过useLexicalComposerContext直接获取编辑器实例:

import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';

// 在组件内部
const [editor] = useLexicalComposerContext();

const getCurrentEditorState = () => {
  const currentState = editor.getEditorState();
  // 后续处理逻辑同上述回调
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:45:43