react-draft-wysiwyg vs react-quill
React 富文本编辑器架构对比:react-draft-wysiwyg 与 react-quill
react-draft-wysiwygreact-quill类似的npm包:

React 富文本编辑器架构对比:react-draft-wysiwyg 与 react-quill

react-draft-wysiwygreact-quill 都是 React 生态中流行的富文本编辑器(WYSIWYG)解决方案,但它们的底层引擎和设计理念截然不同。react-draft-wysiwyg 基于 Facebook 的 Draft.js 构建,提供高度可定制的 React 组件化体验,但受限于底层库的归档状态。react-quill 则是成熟的 Quill 编辑器的 React 封装,拥有强大的富文本处理能力和稳定的 Delta 数据模型,适合需要复杂格式支持的生产环境。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
react-draft-wysiwyg06,463299 kB752-MIT
react-quill07,011405 kB431-MIT

React 富文本编辑器架构对比:react-draft-wysiwyg 与 react-quill

在 React 项目中集成富文本编辑器是一个常见的架构决策。react-draft-wysiwygreact-quill 曾经是两个最热门的选择,但它们的现状和适用场景已经发生了巨大变化。作为架构师,我们需要透过 API 表面,深入到底层引擎、数据模型和维护状态来评估风险。

🚨 核心引擎与维护状态:最关键的决策点

这是两者之间最大的区别,也是决定性的架构风险。

react-draft-wysiwyg 依赖于 Draft.js。Facebook 已经正式归档(Archived)了 Draft.js 仓库,不再接受新功能或主要维护。这意味着底层引擎已经停止演进。

// react-draft-wysiwyg 依赖链
// react-draft-wysiwyg -> draft-js (Archived by Meta)
// 风险:底层不再修复安全漏洞或兼容新 React 版本

react-quill 依赖于 Quill.js。Quill 在经历了长期的 2.0 开发后,近期发布了正式版本,社区依然活跃,底层引擎仍在更新。

// react-quill 依赖链
// react-quill -> quill (Active Maintenance)
// 优势:底层持续修复 bug 并支持新特性

💡 架构建议:除非你正在维护一个无法迁移的旧系统,否则 不要 在新项目中使用 react-draft-wysiwyg。底层库的死亡意味着你的编辑器功能将被冻结在时间中。

📦 数据模型:ContentState vs Delta

编辑器如何存储和序列化数据,直接影响你的后端设计和数据迁移成本。

react-draft-wysiwyg 使用 Draft.js 的 ContentState。这是一种基于 Immutable.js 的复杂 JSON 结构。

// react-draft-wysiwyg: 导出原始 JSON
import { convertToRaw } from 'draft-js';

const rawContent = convertToRaw(editorState.getCurrentContent());
// 输出: { blocks: [...], entityMap: {...} }
// 缺点:结构复杂,难以直接转换为 HTML,依赖特定库解析

react-quill 使用 Delta 格式。这是一种简洁的操作数组,也可以轻松导出为 HTML。

// react-quill: 导出 Delta 或 HTML
const delta = quillRef.current.getDelta(); 
// 输出: { ops: [{ insert: "Hello" }, { insert: "World", attributes: { bold: true } }] }

const html = quillRef.current.root.innerHTML;
// 输出: "<p>Hello<strong>World</strong></p>"
// 优势:Delta 适合协作编辑,HTML 适合直接存储展示

🛠️ 自定义扩展能力:React 组件 vs Blots

当默认工具栏无法满足需求时,两者的扩展方式体现了不同的设计哲学。

react-draft-wysiwyg 允许你直接使用 React 组件来渲染自定义块。这对 React 开发者来说非常直观。

// react-draft-wysiwyg: 自定义块渲染
function MyCustomBlock(props) {
  return <div className="custom-box">{props.children}</div>;
}

const editorProps = {
  blockRendererFn: (block) => {
    if (block.getType() === 'atomic') {
      return {
        component: MyCustomBlock,
        editable: false,
      };
    }
  }
};

<Editor editorState={state} onEditorStateChange={setState} {...editorProps} />

react-quill 使用 Quill 的 Blot 系统。这需要在 Quill 的注册表中定义,不能直接当作普通 React 组件使用,集成难度较高。

// react-quill: 自定义 Blot (需在 Quill 实例外注册)
import Quill from 'quill';
const BlockEmbed = Quill.import('blots/block/embed');

class MyEmbed extends BlockEmbed {
  static create(value) {
    let node = super.create();
    node.setAttribute('data-id', value);
    return node;
  }
}
Quill.register(MyEmbed);

// 在 React 组件中使用
<ReactQuill modules={{ toolbar: [['my-embed', 'custom']] }} />

⚡ 性能与受控模式

在大型表单或高频输入场景下,编辑器的渲染行为至关重要。

react-draft-wysiwyg 强依赖于 editorState 的受控模式。每次击键都会触发 React 状态更新,如果组件树过深,可能导致输入延迟。

// react-draft-wysiwyg: 典型的受控模式
const [editorState, setEditorState] = useState(EditorState.createEmpty());

// 每次 onChange 都会重新渲染整个 Editor 组件
<Editor 
  editorState={editorState} 
  onEditorStateChange={setEditorState} 
/>

react-quill 支持非受控模式(通过 defaultValue)或混合模式,减少不必要的 React 渲染循环。它更多地依赖内部 DOM 管理。

// react-quill: 推荐的非受控或半受控模式
const quillRef = useRef(null);

// 仅在需要时获取内容,减少 React 重渲染
<ReactQuill 
  theme="snow" 
  defaultValue="<p>Initial content</p>"
  ref={quillRef}
/>

// 提交时获取
const content = quillRef.current.editor.root.innerHTML;

🤝 共同点:React 生态集成

尽管底层不同,两者都努力适应 React 的开发习惯。

1. 工具栏配置

两者都允许通过配置对象自定义工具栏。

// react-draft-wysiwyg
const toolbar = {
  options: ['inline', 'blockType', 'list'],
  inline: { options: ['bold', 'italic'] }
};
<Editor toolbar={toolbar} />

// react-quill
const modules = {
  toolbar: [
    [{ 'header': [1, 2, false] }],
    ['bold', 'italic']
  ]
};
<ReactQuill modules={modules} />

2. 样式定制

两者都需要引入 CSS 文件,且都支持通过类名覆盖默认样式。

/* 两者都需要全局 CSS 支持 */
@import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
@import 'react-quill/dist/quill.snow.css';

/* 自定义样式覆盖 */
.DraftEditor-root { font-family: 'CustomFont'; }
.ql-editor { font-family: 'CustomFont'; }

📊 总结对比表

特性react-draft-wysiwygreact-quill
底层引擎Draft.js (已归档 ❌)Quill.js (活跃 ✅)
数据格式Immutable ContentState (JSON)Delta (JSON) 或 HTML
自定义扩展原生 React 组件 (简单)Quill Blots (较复杂)
React 集成深度受控 (可能性能敏感)支持非受控 (性能较好)
长期风险高 (依赖已死)低 (社区维护)
适用场景遗留项目维护新项目、复杂富文本需求

💡 架构师建议

react-draft-wysiwyg 曾经是一个优秀的库,它让 Draft.js 变得易用。但如今,它就像一艘依赖已沉没引擎的船。在 2024 年及以后,选择它意味着你主动承担了底层库停止维护的风险。仅当你在维护一个无法重构的旧系统时,才继续使用它。

react-quill 是目前更务实的选择。虽然它的自定义扩展机制(Blots)不如纯 React 组件直观,但它提供了一个功能完整、经过生产验证的编辑引擎。对于大多数需要富文本功能的企业级应用,它是更安全的基础设施。

最终思考:富文本编辑器是前端最复杂的组件之一。如果可能,评估是否需要完整的 WYSIWYG。很多时候,基于 Markdown 的编辑器(如 react-markdown + Textarea)或更现代的 Headless 编辑器(如 Tiptap)可能是更好的架构选择,它们能提供更长的生命周期和更好的开发体验。

如何选择: react-draft-wysiwyg vs react-quill

  • react-draft-wysiwyg:

    仅建议在维护基于 Draft.js 的遗留项目时选择此包。由于底层依赖 Draft.js 已被官方归档且不再维护,新项目使用它会面临长期的技术债务和安全风险。如果你的团队已经深度绑定 Draft.js 的数据结构且短期内无法迁移,它可以作为过渡方案,否则应避免在新架构中引入。

  • react-quill:

    适合大多数需要稳定富文本编辑功能的新项目,特别是需要处理复杂格式(如表格、特定样式)的场景。虽然 Quill 的自定义扩展(Blots)学习曲线较陡,但其社区活跃且底层引擎持续更新。如果你需要更现代化的 React 集成体验,也可以考虑基于 ProseMirror 或 Tiptap 的替代方案,但在本对比中,它是更稳健的选择。

react-draft-wysiwyg的README

React Draft Wysiwyg

A Wysiwyg editor built using ReactJS and DraftJS libraries. Demo Page.

Build Status

Features

  • Configurable toolbar with option to add/remove controls.
  • Option to change the order of the controls in the toolbar.
  • Option to add custom controls to the toolbar.
  • Option to change styles and icons in the toolbar.
  • Option to show toolbar only when editor is focused.
  • Support for inline styles: Bold, Italic, Underline, StrikeThrough, Code, Subscript, Superscript.
  • Support for block types: Paragraph, H1 - H6, Blockquote, Code.
  • Support for setting font-size and font-family.
  • Support for ordered / unordered lists and indenting.
  • Support for text-alignment.
  • Support for coloring text or background.
  • Support for adding / editing links
  • Choice of more than 150 emojis.
  • Support for mentions.
  • Support for hashtags.
  • Support for adding / uploading images.
  • Support for aligning images, setting height, width.
  • Support for Embedded links, flexibility to set height and width.
  • Option provided to remove added styling.
  • Option of undo and redo.
  • Configurable behavior for RTL and Spellcheck.
  • Support for placeholder.
  • Support for WAI-ARIA Support attributes
  • Using editor as controlled or un-controlled React component.
  • Support to convert Editor Content to HTML, JSON, Markdown.
  • Support to convert the HTML generated by the editor back to editor content.
  • Support for internationalization.

Installing

The package can be installed from npm react-draft-wysiwyg

$ npm install --save react-draft-wysiwyg draft-js

Getting started

Editor can be used as simple React Component:

import { Editor } from "react-draft-wysiwyg";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";
<Editor
  editorState={editorState}
  toolbarClassName="toolbarClassName"
  wrapperClassName="wrapperClassName"
  editorClassName="editorClassName"
  onEditorStateChange={this.onEditorStateChange}
/>;

Docs

For more documentation check here.

Questions Discussions

For discussions join public channel #rd_wysiwyg in DraftJS Slack Organization.

Fund

You can fund project at Patreon.

Thanks

Original motivation and sponsorship for this work came from iPaoo. I am thankful to them for allowing the Editor to be open-sourced.

License

MIT.