@tiptap/core、quill 和 slate 都是用于在 Web 应用中构建富文本编辑器的流行库,但它们的设计哲学和底层架构截然不同。@tiptap/core 是一个无头(headless)编辑器框架,基于 ProseMirror 构建,提供极高的可扩展性而不绑定 UI。quill 是一个开箱即用的富文本编辑器,拥有自己的 DOM 结构和 Delta 数据格式,强调快速集成和标准功能。slate 则是一个完全可定制的 React 编辑器框架,没有预设的 schema,允许开发者完全控制数据结构和渲染逻辑。
@tiptap/core、quill 和 slate 都旨在解决 Web 应用中的富文本编辑问题,但它们的实现路径完全不同。@tiptap/core 侧重于无头架构和扩展性,quill 侧重于开箱即用和标准化,而 slate 侧重于 React 原生和完全定制。让我们从架构师的角度深入对比它们如何处理核心问题。
@tiptap/core 是一个无头编辑器,它只提供逻辑层,不渲染任何 UI。
// tiptap: 初始化编辑器实例
import { useEditor } from '@tiptap/react'
import StarterKit from '@tiptap/starter-kit'
const EditorComponent = () => {
const editor = useEditor({
extensions: [StarterKit],
content: '<p>Hello World</p>',
})
return null // 你需要自己渲染 UI
}
quill 是一个完整的编辑器解决方案,包含 DOM 编辑器和工具栏。
// quill: 初始化编辑器实例
import Quill from 'quill'
const editor = new Quill('#editor-container', {
theme: 'snow',
modules: {
toolbar: ['#toolbar-container']
}
})
// 直接挂载到 DOM 元素
slate 是一个 React 原生编辑器框架,没有预设架构。
// slate: 初始化编辑器实例
import { createEditor } from 'slate'
import { Slate, Editable, withReact } from 'slate-react'
const editor = withReact(createEditor())
const EditorComponent = () => {
const [value, setValue] = useState(initialValue)
return (
<Slate editor={editor} initialValue={value} onChange={setValue}>
<Editable />
</Slate>
)
}
@tiptap/core 使用扩展(Extensions)系统来添加功能。
// tiptap: 添加扩展
import Bold from '@tiptap/extension-bold'
const editor = useEditor({
extensions: [
StarterKit,
Bold.configure({ HTMLAttributes: { class: 'my-bold' } })
],
})
quill 使用模块(Modules)系统来配置功能。
// quill: 配置模块
const quill = new Quill('#editor', {
modules: {
toolbar: [['bold', 'italic'], ['link']],
history: { delay: 2000, maxStack: 500 }
}
})
slate 没有内置的扩展系统,一切靠代码组合。
withReact)或自定义插件增强编辑器。// slate: 自定义插件
const withLinks = editor => {
const { insertData } = editor
editor.insertData = data => {
// 自定义数据插入逻辑
insertData(data)
}
return editor
}
@tiptap/core 使用 ProseMirror 的 JSON 文档模型。
// tiptap: 获取 JSON 内容
const jsonContent = editor.getJSON()
// { type: "doc", content: [{ type: "paragraph", content: [...] }] }
quill 使用 Delta 格式来表示内容和变更。
// quill: 获取 Delta 内容
const delta = quill.getContents()
// { ops: [{ insert: "Hello" }, { insert: "World", attributes: { bold: true } }] }
slate 使用自定义的节点树结构,由开发者定义。
// slate: 自定义节点结构
const initialValue = [
{
type: 'paragraph',
children: [{ text: 'A line of text in a paragraph.' }],
},
]
@tiptap/core 提供官方的 @tiptap/react 包。
useEditor Hook 自动处理生命周期。// tiptap: React Hook
const { editor } = useEditor({
extensions: [StarterKit],
content: contentState,
})
quill 没有官方 React 支持,通常使用封装库。
// quill: React 中手动初始化
useEffect(() => {
const quill = new Quill('#editor', { theme: 'snow' })
quill.on('text-change', () => { /* sync state */ })
}, [])
slate 是专为 React 设计的,完全基于组件。
// slate: 原生 React 组件
<Slate editor={editor} initialValue={value} onChange={setValue}>
<Editable />
</Slate>
尽管架构不同,这三个库都解决了富文本编辑的核心需求。以下是它们的关键重叠点:
// 所有库都支持类似操作
// tiptap: editor.chain().focus().toggleBold().run()
// quill: quill.formatText(index, length, { bold: true })
// slate: Transforms.mark(editor, { type: 'bold' })
// 所有库都支持撤销
// tiptap: editor.chain().focus().undo().run()
// quill: quill.history.undo()
// slate: editor.undo()
// 所有库都支持 HTML 导出
// tiptap: editor.getHTML()
// quill: quill.root.innerHTML
// slate: 需自行实现序列化逻辑
| 特性 | @tiptap/core | quill | slate |
|---|---|---|---|
| 架构类型 | 🧠 无头框架 (ProseMirror) | 📦 完整方案 (DOM) | ⚛️ React 原生框架 |
| 数据格式 | 📄 JSON 文档树 | 📏 Delta 操作序列 | 🧩 自定义节点树 |
| UI 控制 | 🎨 完全自定义 | 🖌️ 内置主题 | 🛠️ 完全自定义 |
| React 支持 | ✅ 官方 Hook | ⚠️ 需手动封装 | ✅ 原生组件 |
| 学习曲线 | 📈 中等 | 📉 低 | 📈 高 |
| 适用场景 | 复杂协作、定制 UI | 快速集成、标准需求 | 高度定制、React 深度集成 |
@tiptap/core 就像是一个强大的发动机 🚗——它提供了驱动编辑器所需的核心动力,但你需要自己制造车身。适合需要长期维护、复杂功能(如协同编辑)且希望 UI 完全定制的企业级应用。
quill 就像是一辆成品自行车 🚲——开箱即用,适合短途出行。适合博客、评论区等需要快速上线、功能标准且不需要深度定制的项目。
slate 就像是一套乐高积木 🧱——你可以搭建任何形状,但需要自己设计结构。适合 React 技术栈深厚、需要特殊数据模型或交互逻辑的创新型产品。
核心思考:选择编辑器不仅仅是选择一个库,而是选择一种数据管理方式。如果你重视数据结构的稳定性,选 @tiptap/core;如果你重视开发速度,选 quill;如果你重视 React 状态的一致性,选 slate。
如果你需要一个稳定、功能强大且不绑定 UI 的编辑器,@tiptap/core 是最佳选择。它基于 ProseMirror,适合需要复杂协作功能或高度自定义工具栏的项目。选择它意味着你愿意花费时间配置扩展,但能获得长期的维护性和稳定性。
如果你需要快速上线一个标准的博客或评论编辑器,quill 是最省力的方案。它内置了工具栏和主题,适合不需要深度定制数据结构的项目。选择它意味着接受其固定的 DOM 结构和 Delta 格式,以换取开发速度。
如果你正在构建一个高度定制化的 React 应用,且需要完全控制编辑器的行为和数据结构,slate 提供了最大的灵活性。它适合需要特殊节点类型或复杂交互的场景。选择它意味着你需要自己处理更多底层逻辑,包括序列化和渲染细节。
Tiptap is a headless wrapper around ProseMirror – a toolkit for building rich text WYSIWYG editors, which is already in use at many well-known companies such as New York Times, The Guardian or Atlassian.
Documentation can be found on the Tiptap website.
Tiptap is open sourced software licensed under the MIT license.