Editor.js 专注于结构化内容创作
其基于块的模型非常适合文章、文档和CMS内容,应用需要存储和处理结构化数据。作者编写一组类型区块;编辑者保证数据的形状,并故意保持对其外观的沉默。这种沉默正是其特点——同一文档可以被网站、移动应用、通讯或搜索索引以各自的条件渲染。
PageKit — 可自托管的 GrapesJS 建站工具,附完整源码。 获取抢先体验
比较GrapesJS和Editor.js,内容结构化、视觉页面构建、HTML/CSS编辑、JSON数据、组件、可扩展性、SaaS应用和CMS集成。Editor.js 围绕结构化内容块设计。GrapesJS 围绕视觉编辑和页面构建工作流程设计。
如果你只读过一个部分,就读这个。下面的两个列表不是排名——它们是两个不同的工作,大多数产品显然都需要其中一个。
这些工具在基于块的编辑中有重叠,但它们是围绕不同编辑器模型设计的。
其基于块的模型非常适合文章、文档和CMS内容,应用需要存储和处理结构化数据。作者编写一组类型区块;编辑者保证数据的形状,并故意保持对其外观的沉默。这种沉默正是其特点——同一文档可以被网站、移动应用、通讯或搜索索引以各自的条件渲染。
其画布、组件模型、块、样式系统、资产和存储能力使其适合页面构建器及其他视觉编辑产品。作者会排列和样式化嵌套的组件树,并在工作过程中看到结果。因此,编辑者需要对布局、断点、选择器和资源的意见——而内容编辑没有理由持有这些意见。
上述两种描述都不是限制。它们是设计决策,双方都买了对方放弃的东西:Editor.js放弃了布局控制,换取了可以随处渲染的内容,而GrapesJS则放弃了格式可移植性,直接控制成品页面。
这两个编辑器都是你挂载在自己应用中的库,而在两边,你的应用负责存储、认证、权限和最终渲染。不同的是中间的那个环:编辑器本身负责什么,以及它交还什么。
结构化文档上的创作层。
Editor.js 将内容编辑与展示分离,生成结构化的块状数据。您的应用程序决定每种块类型在渲染时的样貌,这正是为什么相同内容可以直接流向网页、移动应用、电子邮件摘要或 API 回复而无需重写。
一个覆盖组件树的可视化编辑图层。
GrapesJS 提供可视化编辑层——画布、组件、块、样式、资源、命令和插件——并允许周边应用控制存储、发布和业务逻辑。作者在画布上的安排决定了页面的呈现效果,因此编辑者需要对布局有内容编辑没有的意见。
先看所有权芯片,再看盒子。这两个编辑器都不是平台:没有托管,没有用户管理,没有发布流水线,也没有CDN。这张图回答的问题不是哪个库做得更多,而是哪个库给你的应用提供了产品真正需要存储的数据。
Editor.js 文档是一组有序的打字块。没有画布和布局树,因为文档不需要——散文是线性的,保持线性的格式意味着在发送到任何地方都能保持一致渲染的格式。
平面序列是文章的正确形状。由于结构不带布局,一个存储的文档可以驱动网页、原生应用界面、RSS项目和纯文本摘要,而无需转换。
Editor.js 可以通过自定义 Tools 和块进行扩展。Tool 控制自己的标记:它在 render() 中构建 DOM 元素,返回 save() 块的数据,可以验证数据,定义粘贴处理和净化规则,并在块设置面板中添加自己的控件。Block Tunes 更进一步,在块旁边保持自身状态。任何你能用块类型表达的东西,都可以构建。
@editorjs/header@editorjs/list@editorjs/image@editorjs/quote@editorjs/table@editorjs/embed@editorjs/code@editorjs/attaches值得一提的是,为了公平对比:原厂 Editor.js 工具箱只提供一种块类型,而 GrapesJS 核心则完全没有块。这两个项目都是有意将内容类型提取成包,这两者都不是批评——这只是说明两个编辑器都是配置的,而非被采用的。官方工具套件 github.com/editor-js
GrapesJS 页面是一个组件树,嵌套深度取决于布局需求。按钮存在于 hero 内部,hero 又存在于页面中——该树的每一层都可以选择、重新样式、重新排序、复制或转换为可重复使用的块。
嵌套是布局可编辑的关键。由于组件知道其父节点和子节点,编辑器可以提供每个元素的样式、每个断点覆盖和可重用结构——而平面序列没有任何地方可以存储这些。
关键区别在于,GrapesJS将视觉版面视为一流的编辑体验。
如果你想看从零组装的部件,而不是描述,十二步构建可以在 GrapesJS 教程.
“两者都产生JSON”是对这两款编辑器最误导的真实说法。下面的两个样本都是真实输出,是运行中的编辑器读取的,而非从文档中复制——它们的形状完全不符。
await editor.save()顶层密钥
{
"time": 1788452414107,
"blocks": [
{
"id": "zRvYGn6Hw8",
"type": "header",
"data": { "text": "Build faster", "level": 2 }
},
{
"id": "bziKUc-t8d",
"type": "paragraph",
"data": { "text": "Editable copy." }
}
],
"version": "2.31.6"
}文档:一个时间戳、一个有序的类型块数组,以及编写该文件的编辑器版本。每个块携带一个类型和一个由其 Tool 定义形状的数据对象。这里没有描述布局或样式,这正是该格式可移植的原因。
editor.getProjectData()顶层密钥
{
"dataSources": [],
"assets": [],
"styles": [
{ "selectors": ["hero"], "style": { "padding-top": "40px", "…": "…" } },
{ "selectors": ["btn"], "style": { "background-color": "rgb(75, 91, 191)", "…": "…" } }
],
"pages": [
{
"id": "SjtXdsYjpE8EJUpL",
"frames": [
{
"id": "6THykH6fmgO6bc7i",
"component": {
"type": "wrapper",
"components": [
{ "tagName": "section", "classes": ["hero"], "components": [
{ "tagName": "h2", "type": "text", "components": [
{ "type": "textnode", "content": "Build faster" }
]},
{ "type": "link", "classes": ["btn"], "attributes": { "href": "#" },
"components": [ { "type": "textnode", "content": "Get started" } ] }
]}
]
}
}
]
}
],
"symbols": []
}一个可编辑的项目:页面,每个页面有框架,包含嵌套的组件树,以及样式规则、资源和任何符号。这是你存储的状态,方便作者重新打开他们的作品——而不是你向访客展示的页面。
GrapesJS 存储代表可编辑项目结构的项目数据,而 HTML 和 CSS 则可生成用于发布和导出工作流程。首次导出时有两件事让所有人感到惊讶,这两点都见于下方:getHtml() 返回包裹在正体元素中的画布,getCss() 将速写属性扩展为长写。
<body><section class="hero"><h2>Build faster</h2><p>Editable copy.</p><a href="#" class="btn">Get started</a></section></body>.hero{padding-top:40px;padding-right:40px;padding-bottom:40px;padding-left:40px;text-align:center;}
.hero h2{margin-bottom:8px;font-size:28px;}
.btn{display:inline-block;border-top-left-radius:8px;background-color:rgb(75, 91, 191);color:rgb(255, 255, 255);}测量输出来自产生上述项目数据的同一画布。通过avoidProtected传递编辑器自己的画布重置,这是编辑的Chrome,而不是你页面的一部分。
没有共享子集。Editor.js 块写着“带此文本的二级标题”;GrapesJS 组件写着“带有这些类的 h2 元素,在本节内,按这些规则样式化”。走一条路时,你必须发明那些从未存储过的标记和布局;走另一条路时,你必须丢弃它们。
如果你是从 Editor.js 迁移,应把这当作内容模型和编辑器模型迁移,而不是简单的 JSON 转换。
看看迁移包含哪些内容下面的每个单元格都标注一个机制,而不是评分。没有刻度和叉号栏,因为用Editor.js做响应式版面编辑的划算是假的——自定义Tool可以做到——而刻度则会误导人。“定制”是诚实的答案,也是工程师估算工作时真正想要的。
如何阅读此表
富文本编辑
Editor.js
内置GrapesJS
内置Editor.js 核心内置内联工具栏;GrapesJS 内置富文本编辑器,可通过插件替换为 CKEditor、TinyMCE、Froala 或 Quill。
基于Block的内容
Editor.js
内置GrapesJS
内置两者都是基于块的。Editor.js 块是序列中的内容类型;GrapesJS 块是将组件插入树状结构的 draggable 预设。
结构化JSON输出
Editor.js
内置GrapesJS
内置Editor.js 返回文档;GrapesJS 返回项目数据。两者都是普通的 JSON,描述的内容不同。
可视化画布
Editor.js
自行实现GrapesJS
内置Editor.js 负责原地编辑内容区域;没有单独的画布表面显示设备宽度和每个元素的选择。
拖放式
Editor.js
官方扩展包GrapesJS
内置Editor.js 核心通过上移 / 下移 Tunes和 blocks.move() API 移动区块;指针拖拽是社区插件。GrapesJS 将组件拖拽到画布上。
HTML/CSS 编辑
Editor.js
自行实现GrapesJS
内置GrapesJS 直接编辑选择器和声明,导出 HTML 和 CSS。在 Editor.js 中,这将是一个你写的 Tool。
响应式布局编辑
Editor.js
自行实现GrapesJS
内置GrapesJS 提供设备宽度和按断点覆盖的格式。Editor.js Tool 可以存储响应式数据,但你既定义了 UI 的定义,也定义了语义。
自定义区块
Editor.js
内置GrapesJS
内置两者都确实具有可扩展性。Editor.js 自定义 Tools 拥有其标记、数据和设置面板;GrapesJS 自定义组件类型拥有其模型、视图和 traits。
Component 模型
Editor.js
内置GrapesJS
内置Editor.js 建模的是 Tools 的序列;GrapesJS 建模的是包含父、子和 traits 的嵌套组件树。
样式管理器
Editor.js
自行实现GrapesJS
内置GrapesJS 有一个 Style Manager 绑定在选择和活动断点上。Editor.js 的样式由渲染器决定。
资产管理
Editor.js
你的应用GrapesJS
内置GrapesJS 有一个 Asset Manager;上传仍然是你的终端。Editor.js 图像处理是官方的 Tool,指向你的上传终端。
可重复使用的布局
Editor.js
自行实现GrapesJS
内置GrapesJS 有符号和块供重复使用。Editor.js 中的可重用内容通常在编辑器上方的应用程序中处理。
多页项目
Editor.js
自行实现GrapesJS
内置GrapesJS 项目数据包含一个页面数组。Editor.js 是每个实例一个文档;多个文档是你应用的模型。
存储
Editor.js
你的应用GrapesJS
内置GrapesJS 有一个带有远程适配器的 Storage Manager,指向你的 API。Editor.js 给你 save(),你会持久保存结果。无论哪种方式,数据库都是你的。
发布工作流程
Editor.js
你的应用GrapesJS
对接集成两者都不发布任何内容。GrapesJS 导出 HTML 和 CSS 交给你的流水线;Editor.js 导出 JSON,渲染器消耗的 JSON。
只读模式
Editor.js
内置GrapesJS
内置Editor.js 自 2.19 版本起就采用了只读模式。GrapesJS 可以锁定组件并禁用编辑功能。
Editor UI 翻译
Editor.js
内置GrapesJS
内置两者都能转换自己的接口。Editor.js 有 i18n 的 API;GrapesJS 有 locale/messages 配置。
SaaS 页面构建器
Editor.js
自行实现GrapesJS
非常契合GrapesJS 被广泛用作页面构建器中的编辑器。在内容编辑器上构建相同产品意味着你自己编写布局编辑器。
可嵌入的可视化编辑器
Editor.js
自行实现GrapesJS
非常契合GrapesJS 可以挂载到 DOM 元素中,通常嵌入在他人的产品中。Editor.js 同样容易嵌入,但嵌入内容编辑器。
白标编辑器
Editor.js
自行实现GrapesJS
非常契合GrapesJS面板、图标和CSS可以整体更换。Editor.js、UI也可以重新设计;需要重新命名的镀铬部件减少了。
CMS 集成
Editor.js
内置GrapesJS
内置两者都与CMS集成。问题在于CMS是存储结构化内容还是视觉布局。
TypeScript 类型
Editor.js
内置GrapesJS
内置两者都在发布的软件包中附带类型声明。具体字段见下表。
Plugin 生态系统
Editor.js
官方扩展包GrapesJS
官方扩展包Editor.js 拥有官方工具包和社区生态系统;GrapesJS 有插件 API 和市场。
开源许可
Editor.js
内置GrapesJS
内置Editor.js 是 Apache-2.0。GrapesJS 核心是 BSD-3-Clause。两者都支持商业和闭源使用。
两列读数相同的行,就是两款编辑器真正做同样事情的行。如果你在扫描决策,重要的行是一边写“内置”,另一边说“定制”的行:这个空白就是你们团队将承担的工作。
| 包装 | 版本 | 许可 | 类型声明 |
|---|---|---|---|
| @editorjs/editorjs | 2.31.6 | Apache-2.0 | types/index.d.ts |
| grapesjs | 0.23.6 | BSD-3-Clause | dist/index.d.ts |
从2026-09-03的npm注册表读取。版本会移动;许可证和出货类型声明是这里的持久事实。注意BSD-3-Clause适用于GrapesJS核心——独立的React封装包是MIT。
十四个具体产品,每个产品都有一个推荐。其中四个指向Editor.js,两个指向两者——如果一个对比页面把所有情况都指向它自己的产品,那你不信任它是对的。
作者写散文。价值在于干净且结构化的内容,在每个频道都呈现相同,而不是每个帖子的布局控制。
文档需要一致的模板和受限的块类型。让每个页面自行布局通常是个问题,而不是功能。
当文章是结构化数据而非标记时,搜索、版本管理和重用都会变得更容易。
如果你的API向多个前端提供内容,存储便携文档比存储一个频道的布局要好得多。
营销页面的存在是为了看起来很具体。布局、间距和断点才是工作重点,它们需要在不部署的情况下可编辑。
阅读指南多页、共享页眉和页脚、每页布局——问题的形状是带有页面数组的组件树。
阅读指南你的用户正在建造他们付费购买的工件。他们需要在建造时看到它。
阅读指南面板、图标和样式可以替换,让编辑器作为产品的一部分阅读,而非作为产品中的客串。
阅读指南挂载到别人应用中的DOM元素中,存储和发布通过有线连接到他们的后端。
阅读指南选择器、声明和可导出标记是交付物。内容编辑器会故意隐藏这三者。
阅读指南当编辑者需要控制最终布局而非作者字段时,CMS 需要一个可视化编辑层。
阅读指南电子邮件模板是在极其严格的限制下进行排版——表格、内联样式、客户端的特殊习惯——这属于布局编辑,而非内容编辑。
阅读指南页面的视觉编辑,帖子的结构化内容。两个创作表面,两个编辑器,一个应用程序。
了解如何分层组合文档本身受限于结构化内容,围绕文档的营销页面进行视觉编辑。
对于混合场景,这两种方案都可能适用,具体取决于主要需求是结构化内容还是视觉版面编辑。在决定安装哪个编辑器之前,先确定产品的核心循环到底是哪一个。
你的用户主要是写内容,还是视觉化地构建他们正在创造的东西?
这个问题比任何功能表都更能决定一切。比较你的用户每周会重复几十次的两个工作流程,然后选择一个循环与其匹配的编辑器。
Editor.js 环路
GrapesJS 环路
对于用户需要视觉化构建页面、模板或布局的SaaS产品,GrapesJS通常是更自然的起点——上面的循环就是产品,在内容编辑器上构建它意味着自己编写布局编辑器。如果你的用户是写作而不是写作,较短的循环是正确的,Editor.js能更快带你完成。
构建 CMS 编辑器有两种诚实的做法,而这个选择先于你安装哪款编辑器。下面两种模型都在生产环境中运行,对各自选择它们的产品来说也都是正确的。
结构化CMS
视觉 CMS
选择取决于用户是需要编写结构化内容,还是视觉化控制最终布局。如果有人需要两者,这也是合理的答案——详见后面关于运行两者部分的部分。
理解区别最简单的方法是使用编辑器。从面板拖入一个模块,点击任意元素,重新样式,切换画布到平板或手机,打开资产管理器——然后看到下面的面板打印出你选择的位置。
是的,但迁移通常是内容模型和编辑器架构的迁移,而不是直接导出/导入操作。没有转换器能读取Editor.js文档并生成GrapesJS项目,因为可视化编辑器所需的布局和标记从文档中就没有。必须有人决定,每个内容类型一次——而下面的十个步骤就是这个决定的组织。
审计你的Tools
列出所有正在使用的Tool,包括那些只有少数旧文档依赖的。长尾部分是迁移过度使用的地方。
识别内容类型
将这些Tools归入产品实际含有的内容类型。几种Tools通常只是同一种类型,只是有变体。
地图块数据
对于每种类型,写下其数据对象所包含的内容,以及视觉等价物需要但数据中不包含的内容。
创建GrapesJS组件
为每个内容类型定义组件类型,配合标记和结构,可视化编辑器将渲染和编辑。
创建traits及其属性
将作者需要编辑的字段显示为traits,这样设置面板就能保留原版Tool的控制。
创建视觉块
为每个组件类型添加一个draggable模块,方便作者插入,这也是Editor.js工具箱的视觉对应物。
地图样式与布局
确定组件中固定的样式,作者可以更改的样式,然后配置Style Manager使其匹配。
模板和内容迁移
用脚本将存储文档按内容类型转换。预计会手工检查样本——自动化输出需要判断。
重做前端
你的渲染器消耗了一个块数组。现在它消耗导出的HTML和CSS,也就是项目数据,这是另一种集成。
验证渲染
比较新旧输出,针对真实文档,而不是夹具,并且保持旧流程可读,直到你完成为止。
同一个标题,两种表达方式。下面的对比刻意做得很小,因为它展示的差距正是迁移的全部难点:右侧出现而左侧没有的每一项,都必须由人来决定。
{
"type": "header",
"data": {
"text": "Build faster",
"level": 2
}
}语义和便携性。它说明内容是什么——一个二级标题——却没有说明应该是什么样子。
{
type: 'text',
tagName: 'h2',
components: [{ type: 'textnode', content: 'Build faster' }],
}一个组件定义:Blocks.add() 和 Components.addType() 所取的内容。注意突然出现的东西——标签、结构、文本节点。这些都不在区块里。
Editor.js 概念
GrapesJS 概念
每个 Tool 都变成一个组件类型:原理相同,但组件拥有一个模型和一个视图,而不是 DOM 元素和 save() 方法。
Tool 数据对象中保存的字段将成为组件属性,traits 则用于作者应可更改的字段。
一个平坦、有序的阵列会变成嵌套树。这一步没有机械性答案——嵌套必须被设计。
你存储的文档模式会变成项目数据,加上你应用程序还需要围绕它建模的内容。
这是一种概念映射,不是通用自动转换器。并非所有Editor.js Tools都能重复使用,也不是所有Editor.js内容都能自动转换——上面的映射是每个内容类型用户应用的,难度完全取决于你旧渲染器中隐含的布局意图程度。
这取决于我们这里看不到的输入,所以下面的三层描述这些输入,而不是承诺持续时间。同样的三个Tools在一个组件渲染JSON的应用中花费一个下午,而在一个包含服务器端渲染、模板库和编辑工作流程的应用中则花费更长时间。
有现成工具,少量自定义代码,还有一个下午就能重写的渲染器。
有定制的Tools和模板,所以每个模板都需要设计出一个视觉对应的版本。
编辑器深度融入渲染、工作流程及其他系统中。
在迁移生产内容之前,请审核当前的Editor.js数据模型和渲染流水线。
相当一部分寻找Editor.js替代品的人并不需要迁移。迁移前有三个值得考虑的结果,其中只有一个是迁移。
如果你的产品存储和渲染结构化内容,而你听到的抱怨是关于块类型而非布局,编辑器本身就不是问题。替换它会让你失去目前免费获得的可移植性。
当结构化内容正是你的产品所需要的
自定义Tools拥有自己的标记、数据和设置面板,Block Tunes可以为每个块持久化状态。令人惊讶的是,许多“我们需要不同的编辑器”需求只需一个Tool。
当你只需要额外的Tools内容时
如果需求确实是一个可视化版面编辑器——着陆页、模板、客户使用的构建器——那么添加一个编辑器才是诚实的答案,而且不必意味着移除你已有的内容编辑器。
当产品还需要一个可视化版面编辑器时
在某些应用中,Editor.js 可以继续作为内容创作工具,而 GrapesJS 负责视觉合成。两个编辑器之间没有相互通信——它们各自服务于同一产品的不同创作面,如图所示。
你的应用程序
结构化内容
帖子、文档以及任何需要在多个地方渲染的内容。
视觉布局
落地页、模板以及任何以布局为交付物的东西。
你不必从零构建所有编辑器功能。GrapesJS 可以通过插件扩展,支持常见工作流程和集成——包括对于从内容编辑器转入的玩家,丰富的文本体验。
用CKEditor 5替换内置富文本编辑器,在画布上进行内联编辑。
TinyMCE 6 作为内联文本编辑器,适合作者已经使用的团队。
Froala 作为画布富文本编辑器,拥有自己的工具栏和插件。
Quill 作为富文本编辑器——一个更轻量的选项,无需协商许可。
除了上述四个,目录还包含了更多内置编辑器的集成和扩展。
如果你的产品已经有设计系统,能释放其类的积木比外观漂亮的积木更重要。
有两个列表真正做了人工智能工作,而不是直接命名。它们之所以直接关联,是因为AI分类中心背后没有发布的产品。
六个产品都是同一个编辑器,只是配置不同。每个产品都有自己的指南,因为有趣的决策在于配置,而不是安装。
编辑器安装在DOM元素中,所以框架问题是如何包装它,而不是它是否能正常工作。下面的每个指南都会介绍布线、生命周期以及让人惊讶的部分。
官方 React 包装器、其必需道具,以及 React 生命周期与编辑器的生命周期冲突。
GrapesJS 与 React 结合动态导入、服务器端渲染约束以及编辑器可以挂载或不挂载的位置。
Next.js 页面构建器挂载到模板参考,以及为什么没有官方的 Vue 封装器可供使用。
GrapesJS 与 Vue 结合Component 生命周期、区域处理以及删除时的编辑器清理。
GrapesJS 与 Angular 结合发布的类型声明、它们能导出和不能导出的内容,以及编译器的最小版本。
GrapesJS 与 TypeScript 结合完全没有框架:脚本标签、容器元素和初始化调用。从这里开始,可以清晰地看到核心。
GrapesJS 教程需要明确说明一点:GrapesJS 核心是框架无关的,可以集成到使用这些框架的应用中——它不使用与 React 或 Vue 相同的组件模型。GrapesJS 中的“组件”是编辑器自身描述画布树节点的模型对象,而非 React 或 Vue 组件,画布渲染的是真实的 DOM,而非框架的虚拟树。封装器将编辑器集成到你的应用中;它们不会将框架的组件放到画布中。
二十个要求,每个一个推荐起始点。Editor.js各六个点,两个点,因为他们实际上指向那里。
| 你的需求 | 推荐的起点 |
|---|---|
| 博客编辑器 | Editor.js |
| 文章编辑 | Editor.js |
| 文档 | Editor.js |
| 结构化内容 | Editor.js |
| JSON优先内容工作流程 | Editor.js |
| 一份文档,多频道 | Editor.js |
| 可视化页面构建器 | GrapesJS |
| 着陆页构建器 | GrapesJS |
| SaaS 页面构建器 | GrapesJS |
| HTML/CSS 编辑器 | GrapesJS |
| 白标可视化编辑器 | GrapesJS |
| 可嵌入的可视化编辑器 | GrapesJS |
| 可视化 CMS 编辑器 | GrapesJS |
| 自定义页面组成 | GrapesJS |
| 响应式布局控制 | GrapesJS |
| 可重复使用的可视化模板 | GrapesJS |
| 电子邮件模板编辑 | GrapesJS |
| 多页项目 | GrapesJS |
| 带博客的营销网站 | 两者皆可 |
| 文档和营销页面 | 两者皆可 |
这两种工具都没有绝对优越。根据你的产品所需的编辑模型来选择。
如果审计指向迁移,GJS.Market可以帮忙处理这对编辑器特有的部分,而不是任何重写的通用部分。
我们的范围基于您的实际数据模型和渲染流程,因此第一轮对话更关注您拥有的设备,而非我们提供的服务。我们不会给出审计前的具体时间,因为诚实的答案取决于上述八个因素。
Editor.js 是结构化内容编辑的强力选择。当用户需要视觉化地构建和自定义页面、布局和组件时,GrapesJS 是强有力的选择。
如果你的产品需要视觉编辑,可以从GrapesJS开始,并在整个应用架构中扩展。如果需要结构化内容,简短的答案才是正确的——而本页希望已经让你明白你读到的是哪种内容。