关于 unlayer-integration
用于在 React、Vue、Angular 或纯 JavaScript 应用中嵌入 Unlayer 编辑器的开发技能,介绍各框架的访问方式、编辑器配置及多实例处理。
主要功能
- 01React、Vue 和 Angular 封装
- 02纯 JavaScript 嵌入方式
- 03各框架对应的编辑器访问方式
- 04设计的保存与加载模式
- 05使用 createEditor() 创建多个实例
适用场景
- 01在 Web 应用中嵌入邮件构建器
- 02加载并保存可编辑设计
- 03分别运行邮件和网页编辑器实例
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ unlayer/ unlayer-skills --skill unlayer-integration安装后在 Claude Code 中输入/unlayer-integration确认已加载。
详细介绍
集成 Unlayer Editor
概述
Unlayer 提供 React、Vue 和 Angular 的官方包装组件,以及纯 JavaScript 嵌入方式。所有包装组件都共用相同的底层 API,只有编辑器的访问方式不同。
此技能涵盖邮件、页面、弹窗和文档构建器。对于独立的 Image Editor 或
@unlayer/react-image-editor,请使用 unlayer-image-editor。
选择哪个框架?
| 框架 | 包 | 安装 | 编辑器访问方式 |
|---|---|---|---|
| React | react-email-editor | npm i react-email-editor | useRef<EditorRef> → ref.current?.editor |
| Vue | vue-email-editor | npm i vue-email-editor | this.$refs.emailEditor.editor |
| Angular | angular-email-editor | npm i angular-email-editor | @ViewChild → this.emailEditor.editor |
| 纯 JS | CDN 脚本标签 | <script> 嵌入 | 全局 unlayer 对象 |
⚠️ 安装任何 Unlayer 包之前,请先确认该版本已发布到 npm:
npm view react-email-editor version # check latest published version切勿固定使用未经确认的版本号。使用
npm install <package> --save(不指定版本)以获取最新版本,或运行npm view <package> versions --json查看所有可用版本。
React(完整可运行示例)
npm install react-email-editor --save
import React, { useRef, useState } from 'react';
import EmailEditor, { EditorRef, EmailEditorProps } from 'react-email-editor';
const EmailBuilder = () => {
const emailEditorRef = useRef<EditorRef>(null);
const [saving, setSaving] = useState(false);
// Save design JSON + export HTML to your backend
const handleSave = () => {
const unlayer = emailEditorRef.current?.editor;
if (!unlayer) return;
setSaving(true);
unlayer.exportHtml(async (data) => {
try {
const response = await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
design: data.design, // Save this — needed to edit later
html: data.html, // The rendered HTML output
}),
});
if (!response.ok) throw new Error('Save failed');
console.log('Saved successfully');
} catch (err) {
console.error('Save error:', err);
} finally {
setSaving(false);
}
});
};
// Load a saved design when editor is ready
const onReady: EmailEditorProps['onReady'] = async (unlayer) => {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
unlayer.loadDesign(saved.design); // Pass the saved design JSON
}
} catch (err) {
console.log('No saved design, starting blank');
}
};
return (
<div>
<button onClick={handleSave} disabled={saving}>
{saving ? 'Saving...' : 'Save'}
</button>
<EmailEditor
ref={emailEditorRef}
onReady={onReady}
options={{
projectId: 123456, // Dashboard > Project > Settings
displayMode: 'email',
}}
/>
</div>
);
};
export default EmailBuilder;
后端应接受并返回:
// POST /api/templates — save
{ design: object, html: string }
// GET /api/templates/:id — load
{ design: object, html: string, updatedAt: string }
React 属性:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
options | Object | {} | 所有 unlayer.init() 选项(projectId、displayMode 等) |
tools | Object | {} | 每个工具的配置 |
appearance | Object | {} | 主题和面板设置 |
onReady | Function | — | 编辑器就绪时调用(接收 unlayer 实例) |
onLoad | Function | — | iframe 加载时调用(就绪前) |
style | Object | {} | 容器内联样式 |
minHeight | String | '500px' | 编辑器最小高度 |
文档:https://docs.unlayer.com/builder/react-component GitHub:https://github.com/unlayer/react-email-editor
Vue(完整可运行示例)
npm install vue-email-editor --save
<template>
<div id="app">
<button v-on:click="handleSave" :disabled="saving">
{{ saving ? 'Saving...' : 'Save' }}
</button>
<EmailEditor ref="emailEditor" v-on:load="editorLoaded" />
</div>
</template>
<script>
import { EmailEditor } from 'vue-email-editor';
export default {
components: { EmailEditor },
data() {
return { saving: false };
},
methods: {
async editorLoaded() {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
this.$refs.emailEditor.editor.loadDesign(saved.design);
}
} catch (err) {
console.log('No saved design, starting blank');
}
},
handleSave() {
this.saving = true;
this.$refs.emailEditor.editor.exportHtml(async (data) => {
try {
await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design: data.design, html: data.html }),
});
} catch (err) {
console.error('Save error:', err);
} finally {
this.saving = false;
}
});
},
},
};
</script>
属性: minHeight、options、tools、appearance、locale、projectId。
文档:https://docs.unlayer.com/builder/vue-component GitHub:https://github.com/unlayer/vue-email-editor
Angular(完整可运行示例)
npm install angular-email-editor --save
模块(app.module.ts):
import { EmailEditorModule } from 'angular-email-editor';
@NgModule({ imports: [EmailEditorModule] })
export class AppModule {}
组件(app.component.ts):
import { Component, ViewChild } from '@angular/core';
import { EmailEditorComponent } from 'angular-email-editor';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
@ViewChild(EmailEditorComponent)
private emailEditor: EmailEditorComponent;
saving = false;
async editorLoaded() {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
this.emailEditor.editor.loadDesign(saved.design);
}
} catch (err) {
console.log('No saved design');
}
}
handleSave() {
this.saving = true;
this.emailEditor.editor.exportHtml(async (data) => {
try {
await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design: data.design, html: data.html }),
});
} catch (err) {
console.error('Save error:', err);
} finally {
this.saving = false;
}
});
}
}
模板(app.component.html):
<div>
<button (click)="handleSave()" [disabled]="saving">
{{ saving ? 'Saving...' : 'Save' }}
</button>
<email-editor (loaded)="editorLoaded($event)"></email-editor>
</div>
纯 JavaScript
<script src="https://editor.unlayer.com/embed.js"></script>
<div id="editor-container" style="height: 700px;"></div>
<script>
unlayer.init({
id: 'editor-container',
projectId: 1234,
displayMode: 'email',
});
unlayer.addEventListener('editor:ready', async function () {
try {
const response = await fetch('/api/templates/123');
if (response.ok) {
const saved = await response.json();
unlayer.loadDesign(saved.design);
}
} catch (err) {
console.log('Starting blank');
}
});
function handleSave() {
unlayer.exportHtml(async function (data) {
await fetch('/api/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ design: data.design, html: data.html }),
});
});
}
</script>
多个编辑器实例
使用 createEditor() 而不是 init():
const editor1 = unlayer.createEditor({ id: 'email-editor', displayMode: 'email' });
const editor2 = unlayer.createEditor({ id: 'web-editor', displayMode: 'web' });
editor1.loadDesign(emailDesign);
editor2.loadDesign(webDesign);
常见错误
| 错误 | 修正方法 |
|---|---|
| 容器过小 | 最小尺寸为 1024px 宽 x 700px 高。编辑器会填满容器。 |
| 就绪前调用方法 | 始终等待 editor:ready 事件或 onReady 回调 |
多个编辑器使用 init() | 改用 unlayer.createEditor() |
缺少 projectId | 从 Dashboard > Project > Settings 获取 |
| 只保存 HTML,不保存设计 JSON | 始终同时保存两者——设计 JSON 可让用户之后继续编辑 |
| 保存时没有加载状态 | 禁用保存按钮,防止重复保存 |
| 固定使用不存在的包版本 | 固定版本前运行 npm view <package> version 确认。使用 npm install <package> --save(不指定版本)以获取最新版本。 |
故障排除
| 错误 | 原因 | 修复方法 |
|---|---|---|
| 编辑器显示空白 | 容器 div 的高度为 0 | 设置明确的高度:min-height: 700px |
editor:ready 从未触发 | 脚本未加载或 id 错误 | 检查 id 是否与现有的 div 匹配,并检查网络选项卡中的 embed.js |
ref.current?.editor 未定义 | 在挂载前访问 | 仅在 onReady 回调中使用 |
| 设计未加载 | JSON 格式错误 | 验证 JSON,并检查 schemaVersion 字段 |