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

Draft JS从外部脚本更新EditorState如何保留撤销/重做栈

问题根因

你当前的实现丢失撤销/重做栈的核心原因是使用了EditorState.createWithContent创建全新的编辑器状态,该方法会完全丢弃原有编辑器实例的历史栈数据。

解决方案

要保留历史栈需要使用DraftJS内置的Modifier API处理内容修改,再通过EditorState.push提交变更,DraftJS会自动将本次修改记录到历史栈中,完整实现代码如下:

import { Modifier, EditorState, BlockMapBuilder } from 'draft-js';

function appendBlocksFromHtml(editorState, htmlString) {
  const newBlockData = htmlToDraft(htmlString);
  const currentContent = editorState.getCurrentContent();
  // 合并新旧实体映射,避免插入带实体的内容(链接、图片等)时报错
  const mergedEntityMap = {
    ...currentContent.getEntityMap(),
    ...newBlockData.entityMap
  };
  const contentWithMergedEntities = currentContent.set('entityMap', mergedEntityMap);
  // 构建要插入的块片段
  const fragment = BlockMapBuilder.createFromArray(newBlockData.contentBlocks);
  // 获取文档末尾的选中状态
  const selectionAtEnd = contentWithMergedEntities.getSelectionAfter();
  
  // 用Modifier API插入片段,生成新的内容状态
  const newContent = Modifier.insertFragment(
    contentWithMergedEntities,
    selectionAtEnd,
    fragment
  );
  
  // 用EditorState.push提交修改,会自动保留历史栈
  const newEditorState = EditorState.push(
    editorState,
    newContent,
    'insert-fragment'
  );
  
  // 移动光标到末尾
  return EditorState.moveSelectionToEnd(newEditorState);
}

注意事项

  • EditorState.push的第三个参数'insert-fragment'为修改类型标记,DraftJS会根据该类型自动处理历史栈的合并逻辑,你也可以根据自身业务场景自定义修改类型。
  • 如果需要将内容插入到指定位置而非文档末尾,仅需将selectionAtEnd替换为对应位置的SelectionState实例即可。
  • 直接手动拼接块数组的方式会跳过DraftJS的内部内容校验逻辑,使用官方ModifierAPI可以避免出现块结构、实体关联异常的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 19:30:04