为什么要把GrapesJS和Svelte搭配
GrapesJS 是一个不受框架限制、授权 MIT 许可的拖放构建器,所以
直接插入一个没有包装库的 SvelteKit 应用。唯一需要遵守的规则
GrapesJS 需要 DOM ——它必须在浏览器中运行,而不是在浏览器中运行
服务器端渲染。斯苗特的 onMount 生命周期说明了这一点
简单:它只在客户端触发,而编辑器正好该在客户端。
本指南介绍了生产准备的安装方案:安装,安全挂载编辑器, 将内容保存到后端,导出干净的HTML和CSS。
1. 安装GrapesJS
npm install grapesjs
无需专用Svelte适配器。你可以以后添加预设(比如
grapesjs-preset-webpage 或者
GJS 的插件。一旦核心编辑器运行,市场。
2. 将编辑器挂载到客户端
创建一条路线,例如。 src/routes/editor/+page.svelte绑定 a
容器元素,然后在 和 中初始化 GrapesJS onMount
返回拆解,使实例在导航时被销毁。
<script>
import { onMount } from 'svelte';
import grapesjs from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';
let container; // bound to the editor div
let editor; // GrapesJS instance
onMount(() => {
editor = grapesjs.init({
container,
height: '100vh',
fromElement: false,
storageManager: false, // we wire storage manually in step 3
components: '<h1>Hello from GrapesJS</h1>',
style: 'h1 { font-family: sans-serif; }',
});
// Clean up listeners + DOM when the component unmounts.
return () => editor?.destroy();
});
</script>
<div bind:this={container}></div>
因为 onMount 从未在服务器上运行,编辑器是被创建的
仅在浏览器中——没有SSR错误,没有 window is not defined。
3. 将内容保存到后台
最简单的方法是通过保存按钮读取当前文档, POST到你的API:
<script>
async function save() {
const payload = {
html: editor.getHtml(),
css: editor.getCss(),
// Full editable project (for re-loading into the editor later):
project: editor.getProjectData(),
};
await fetch('/api/pages', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
}
</script>
<button on:click={save}>Save</button>
喜欢自动存档吗?配置存储管理器,而不是
storageManager: false:
storageManager: {
type: 'remote',
stepsBeforeSave: 3,
options: {
remote: {
urlStore: '/api/pages',
urlLoad: '/api/pages/load',
},
},
}
4. 导出生产HTML和CSS
editor.getHtml() 并 editor.getCss() 返回
将标记和样式渲染为字符串。需要独立的版本时可以合并
文件:
const html = editor.getHtml();
const css = editor.getCss();
const document = `<!doctype html>
<html>
<head><style>${css}</style></head>
<body>${html}</body>
</html>`;
重新加载已保存的项目
要在编辑器中重新打开页面,请通过以下方式将存储的项目数据传回。
editor.loadProjectData(saved.project) 在 init 或 Set 之后
projectData 在初始化配置里。
前提条件
开始之前,确保你有Node.js 18或更新的设备和一个SvelteKit
用 创建的项目。 npm create svelte@latest你不需要
Svelte 专用的 GrapesJS 包装器——GrapesJS 不受框架限制,作为
普通的ES模块,所以同样的方法适用于SvelteKit应用,也就是普通的Svelte。
SPA,或者嵌入在更大页面中的Svelte组件。基本理解
斯韦尔特的生命周期(onMount, onDestroy) 以及 的 ,其中
代码运行(服务器与浏览器)是你唯一需要跟上的。
向编辑器添加自定义方块
在用户有构建模块需要拖拽之前,裸编辑器其实用处不大
落在画布上。之后立即向区块管理器注册
grapesjs.init。每个模块是一个标签加上 HTML(或一个组件)
定义)它直接出现在页面上:
editor.BlockManager.add('hero', {
label: 'Hero section',
category: 'Sections',
content: `
<section class="hero">
<h1>Headline</h1>
<p>Supporting copy goes here.</p>
<a href="#">Call to action</a>
</section>`,
});
editor.BlockManager.add('two-cols', {
label: 'Two columns',
category: 'Layout',
content: '<div class="row"><div class="cell"></div><div class="cell"></div></div>',
});
将 category 与该物业相关方块归一组,以确保面板保持完整
组织,并从GJS获取现成的块库和预设。市场
当你想要一个更丰富的起始套装,而不是每块都手工建造时,
坚持到真实后端(深度分析)
在SvelteKit应用中,接收存档的自然位置是
+server.js 终点。把存储管理器接到它上,然后发送你的
请求头中的认证令牌:
// in grapesjs.init(...)
storageManager: {
type: 'remote',
autosave: true,
stepsBeforeSave: 3,
options: {
remote: {
urlStore: '/api/pages',
urlLoad: '/api/pages',
headers: { Authorization: `Bearer ${token}` },
},
},
}
// src/routes/api/pages/+server.js
import { json } from '@sveltejs/kit';
let page = {}; // swap for your database
export async function GET() {
return json(page);
}
export async function POST({ request }) {
page = await request.json(); // the full GrapesJS project
return json({ status: 'ok' });
}
为了完全控制,你可以注册一个自定义的存储适配器,而不是遥控器 预设——当你需要乐观界面、离线队列或非HTTP存储时非常有用:
editor.Storage.add('svelte-store', {
async load() {
const res = await fetch('/api/pages');
return res.ok ? res.json() : {};
},
async store(data) {
await fetch('/api/pages', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
},
});
// then: storageManager: { type: 'svelte-store' }
表演技巧
GrapesJS 依赖很大,所以只加载它在需要的地方。进口
它动态地在 onMount (await import('grapesjs'))
这样它就不会出现在主捆绑包里,也不会出现在服务器渲染路径里。永远撕开
编辑器关闭,组件 editor.destroy() 卸载时——
在SvelteKit客户端导航时,一个泄露实例保留了监听器
DOM节点活着,它们会积累。调 stepsBeforeSave 音
自动保存不会对每个小改动都触发,只有在某些时候才会懒惰地加载重插件
用户实际上会打开需要这些工具的功能。
安全考量
GrapesJS忠实地存储画布上的标记,所以请选择导出的 如果非管理员用户可以编辑页面,则表示HTML为不可信:输出时进行净化(a 经过服务器端消毒处理)然后才向其他访客展示。保护 保存端点,使用真实的认证和授权——永远不要接受 未经认证的帖子覆盖页面。如果你加载第三方插件到 编辑,把他们的版本钉顶并审核,因为它们可以完全访问 对编辑和页面。
排查常见问题
“文档未定义” 意味着GrapesJS在SSR期间运行——移动
导入和 init 内部 onMount。 画布
看起来无样式 意味着样式表导入缺失;添加
import 'grapesjs/dist/css/grapes.min.css'。 编辑器是
空白 通常表示容器元素尚未绑定,当
init run — 绑定它 并 bind:this init in
onMount。 413的存档失败 意味着项目成功
有效载荷超过服务器的体型限制;在端点上加高。
什么时候用GrapesJS搭配Svelte。
当你需要嵌入真实的可视化页面或邮件时,GrapesJS 是正确的选择 Svelte产品内置的构建器——一个SaaS页面编辑器、一个内容管理系统表面(CMS)、一个 通讯撰写器——你想拥有编辑器、存储和HTML的版权 输出。如果你只需要在单一字段内进行富文本编辑,那就用打火机 富文本组件更合适。用于拖放全页构图 布局、样式管理器和干净的 HTML/CSS 导出,GrapesJS 提供了更多功能 而非文本编辑器,同时保持MIT许可和自托管。
SvelteKit 常见的陷阱
几乎所有出错的设置都被三个错误解释。首先,将GrapesJS导入模块顶部而非内部 onMount ——这样在SSR期间运行并抛 document is not defined出 。让导入的 lazy (await import('grapesjs')) 留在生命周期钩子里。其次,忘记返回 editor.destroy():SvelteKit的客户端路由经常重载组件,泄露的编辑器实例会堆积监听器和内存。第三,缺少样式表——没有 grapesjs/dist/css/grapes.min.css 画布渲染时会显示无样式且看起来坏掉。解决这三者后,集成在导航、热装填和生产版本中稳定。
下一步
核心编辑器运行后,用模块和插件扩展它。参见相关内容 GrapesJS 在 React 中的 框架指南和 GrapesJS 在 Vue 中浏览现成产品 GrapesJS 插件和模板,或者试试编辑器 直接来自 GJS。市场主页。
常见问题
GrapesJS 能和 SvelteKit 的服务器端渲染一起使用吗?
是的。GrapesJS 需要 DOM,所以把它安装在 onMount里面,只有
运行在浏览器中。绕过它的路由仍然可以被服务器渲染;只有
编辑器实例仅支持客户端。
我该如何在 Svelte 应用中保存 GrapesJS 的内容?
使用存储管理器,并 type: 'remote' POST 项目数据于
你的后端,或者读取 editor.getHtml() 和
editor.getCss() 用保存键自己发。
卸载时我需要销毁编辑器吗?
是的。从so GrapesJS回归 editor.destroy() onMount
在客户端导航时移除监听器和DOM节点,防止
内存泄漏。
