@iss-ai/window-message-bus
v0.0.8
Published
window消息封装为bus
Downloads
773
Maintainers
Readme
@iss-ai/window-message-bus
Window 消息封装为 bus,提供基于 postMessage 的跨窗口通信解决方案。支持主窗口与 iframe 之间的双向消息传递,以及编辑器场景下的专用通信协议。
特性
- 🚀 跨窗口通信:支持主窗口与 iframe 之间的双向消息传递
- 🔒 安全验证:支持来源域名白名单验证
- 📦 多格式构建:同时提供 CJS、ESM、UMD、IIFE 四种模块格式
- 🎯 类型安全:完整的 TypeScript 类型定义
- 🛠️ 编辑器专用:内置 EditorMessageBus 用于编辑器与 iframe 通信
- 🧪 测试友好:基于 Jest 和 jsdom 的完整测试覆盖
安装
npm install @iss-ai/window-message-bus或
pnpm add @iss-ai/window-message-bus快速开始
基础用法 - WindowMessageBus
import { WindowMessageBus } from '@iss-ai/window-message-bus';
// 创建实例
const bus = new WindowMessageBus({
sourceId: 'main-window',
debug: true,
});
// 监听消息
bus.on('custom-event', (data, context) => {
console.log('收到消息:', data, context);
});
// 发送消息到父窗口
bus.emitTo('parent', 'custom-event', { message: 'Hello from iframe!' });
// 发送消息到指定窗口
bus.emitTo(window.parent, 'custom-event', { message: 'Hello parent!' });编辑器场景 - EditorMessageBus
import { EditorMessageBus } from '@iss-ai/window-message-bus';
// 主窗口(编辑器容器)
const editorBus = new EditorMessageBus({
sourceId: 'editor-main',
debug: true,
});
// 监听编辑器就绪
editorBus.onReady((data) => {
console.log('编辑器已就绪:', data);
});
// 设置编辑器数据
editorBus.setData({ nodes: [], edges: [] });
// 监听内容变更
editorBus.onChange((change) => {
console.log('内容变更:', change);
});
// 监听保存
editorBus.onSave((data) => {
console.log('保存数据:', data);
});
// 发送保存指令
editorBus.save();
// iframe 端
const iframeEditorBus = new EditorMessageBus({
sourceId: 'editor-iframe',
debug: true,
});
// 通知主窗口已就绪
iframeEditorBus.isReady({ version: '1.0.0' });
// 接收设置数据指令
iframeEditorBus.onSetData((data) => {
renderEditor(data);
});
// 内容变更时通知主窗口
iframeEditorBus.change({ type: 'update', elementId: 'node-1' });
// 导出数据
const data = await iframeEditorBus.exportData();API 文档
WindowMessageBus
构造函数选项
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| debug | boolean | false | 是否开启调试模式 |
| debugPrefix | string | '[WindowMessageBus]' | 调试日志前缀 |
| sourceId | string | 自动生成 | 当前实例的唯一标识 |
| allowedOrigins | string[] | ['*'] | 允许的消息源域名 |
| serialize | (data: any) => string | JSON.stringify | 消息序列化函数 |
| deserialize | (str: string) => any | JSON.parse | 消息反序列化函数 |
主要方法
| 方法 | 说明 |
|------|------|
| emitTo(target, type, data) | 向指定目标发送消息 |
| on(type, handler) | 监听消息事件 |
| off(type, handler) | 取消监听消息事件 |
| once(type, handler) | 监听一次消息事件 |
| getSourceId() | 获取当前实例的 sourceId |
PostMessageTarget 类型
type PostMessageTarget = WindowProxy | 'parent' | 'self' | 'top';EditorMessageBus
继承自 WindowMessageBus,提供以下专用方法:
就绪相关
| 方法 | 说明 |
|------|------|
| isReady(data, target?) | 发送编辑器已就绪消息 |
| onReady(handler) | 监听编辑器已就绪事件 |
数据设置
| 方法 | 说明 |
|------|------|
| setData(data, target?) | 设置编辑器数据 |
| onSetData(handler) | 监听设置数据事件 |
配置设置
| 方法 | 说明 |
|------|------|
| setConfig(config, target?) | 设置编辑器配置 |
| onSetConfig(handler) | 监听设置配置事件 |
内容变更
| 方法 | 说明 |
|------|------|
| change(changeData, target?) | 发送内容变更消息 |
| onChange(handler) | 监听内容变更事件 |
保存
| 方法 | 说明 |
|------|------|
| save(options?, target?) | 发送保存消息 |
| onSave(handler) | 监听保存事件 |
导出功能
| 方法 | 说明 |
|------|------|
| exportSVG(options?, target?) | 导出 SVG |
| onExportSVG(handler) | 监听 SVG 导出响应 |
| exportPNG(options?, target?) | 导出 PNG |
| onExportPNG(handler) | 监听 PNG 导出响应 |
| exportData(options?, target?) | 导出数据 |
| onExportData(handler) | 监听数据导出响应 |
其他功能
| 方法 | 说明 |
|------|------|
| getData(target?) | 获取编辑器数据 |
| onGetData(handler) | 监听获取数据响应 |
| thumbnail(options?, target?) | 生成缩略图 |
| onThumnail(handler) | 监听缩略图响应 |
| preview(options?, target?) | 预览 |
| onPreview(handler) | 监听预览响应 |
类型定义
MessageData
interface MessageData {
type: string; // 事件类型
data: any; // 消息数据
messageId?: string; // 消息 ID
sourceId?: string; // 来源标识
}MessageContext
interface MessageContext {
origin: string; // 消息来源域名
source: WindowProxy; // 消息来源窗口引用
messageId?: string; // 消息 ID
sourceId?: string; // 消息来源标识
}EditorData
interface EditorData {
[key: string]: any;
}EditorConfig
interface EditorConfig {
canvas?: {
width?: number;
height?: number;
backgroundColor?: string;
grid?: {
enabled?: boolean;
size?: number;
color?: string;
};
snapToGrid?: boolean;
};
toolbar?: {
enabled?: boolean;
position?: 'top' | 'bottom' | 'left' | 'right';
items?: string[];
};
propertiesPanel?: {
enabled?: boolean;
position?: 'left' | 'right';
width?: number;
};
minimap?: {
enabled?: boolean;
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
};
interaction?: {
zoom?: { enabled?: boolean; minScale?: number; maxScale?: number };
pan?: { enabled?: boolean; sensitivity?: number };
selection?: { enabled?: boolean; multiple?: boolean };
drag?: { enabled?: boolean; snap?: boolean };
};
theme?: {
mode?: 'light' | 'dark' | 'auto';
colors?: {
primary?: string;
secondary?: string;
background?: string;
surface?: string;
};
};
[key: string]: any;
}使用示例
主窗口与 iframe 通信
主窗口代码:
<!DOCTYPE html>
<html>
<head>
<title>Main Window</title>
</head>
<body>
<iframe id="editor" src="editor.html"></iframe>
<script src="https://unpkg.com/@iss-ai/window-message-bus"></script>
<script>
const bus = new WindowMessageBus.WindowMessageBus({
sourceId: 'main-window',
debug: true,
});
// 监听 iframe 消息
bus.on('editor:message', (data) => {
console.log('收到 iframe 消息:', data);
});
// 向 iframe 发送消息
setTimeout(() => {
bus.emitTo('parent', 'init-editor', { config: { theme: 'dark' } });
}, 1000);
</script>
</body>
</html>iframe 代码:
<!DOCTYPE html>
<html>
<head>
<title>Iframe Editor</title>
</head>
<body>
<div id="editor">Editor Content</div>
<script src="https://unpkg.com/@iss-ai/window-message-bus"></script>
<script>
const bus = new WindowMessageBus.WindowMessageBus({
sourceId: 'iframe-editor',
debug: true,
});
// 监听主窗口消息
bus.on('init-editor', (data) => {
console.log('初始化编辑器:', data);
});
// 向主窗口发送消息
bus.emitTo('parent', 'editor:message', { content: 'Hello from iframe!' });
</script>
</body>
</html>脚本命令
# 构建
npm run build
# 测试
npm test
# 发布
npm run pub
# 覆盖率
npm run coveralls
# TypeScript 检查
npm run tsc浏览器支持
- Chrome >= 60
- Firefox >= 55
- Safari >= 11
- Edge >= 79
许可证
MIT License
贡献
欢迎提交 Issue 和 Pull Request!
