🚀 优雅的 跨窗口通信 与 全局页面管理 解决方案 cross-window-message
分享一个本人开发的 跨窗口通信 与 全局页面管理
0. 特性
- 支持不同页面之间的 定向通信 和 广播通信
- 支持任意方式打开的页面,不局限于 window.open 方法
- 支持多个由主页面打开的子页面之间通信
- 支持标记和追踪各个页面的状态,方便进行全局页面管理
- 支持关闭子页面等多种方法调用
- 支持监听页面事件
- 页面存活检查,保证页面状态同步
- typescript开发,使用简单,体积小巧
1. 安装使用
1.1 npm
npm i cross-window-message
import initMessager from 'cross-window-message';
1.2 cdn 引入
<script src="https://cdn.jsdelivr.net/npm/cross-window-message/cross-window-message.min.js"></script>
<script>
console.log(initMessager);
</script>
2. 使用介绍
cross-window-message
原理是基于 window.onstorage 事件以及 localStorage 进行跨页面通信
为什么不使用 window.open 配合 postMessage和onMessage事件,有以下几点原因
- 使用条件比较苛刻,只适用于使用 window.open 打开的页面
- 多个由主页面打开的子页面之间不方便通信
- 多个页面之间无法广播通信
- 无法标记各个页面状态
使用流程
进入页面时调用 initMessager
生成一个 Messager, 该方法支持传入两个可选参数,pageName 和 pageId
pageName 表示页面名称,可以有相同的页面。如果不传入则使用当前页面的 pathname
pageId 表示页面ID,每一个新页面必须是唯一的。如果不传入会生成一个默认的唯一id
import initMessager from 'cross-window-message';
const messager = initMessager('pageName', 'pageId');
之后各个页面之间的通信都是依赖于这个 Messager 进行
3. api
3.1 Messager ts声明
interface IMessager {
pageId: string;
pageName: string;
postMessage(data: any, messageType?: number | string): void;
postMessageToTargetId(targetPageId: string, data: any, messageType?: number | string): void;
postMessageToTargetName(targetPageName: string, data: any, messageType?: number | string): void;
onMessage(fn: (msgData: IMsgData) => void): () => void;
onUnload(func: (event: BeforeUnloadEvent) => void): () => void;
onClick(func: (event: MouseEvent) => void): () => void;
onShow(func: (event: Event) => void): () => void;
onHide(func: (event: Event) => void): () => void;
method: {
closeOtherPage(): void;
closeOtherSamePage(): void;
alertInTargetName(text: string | number, pageName: string): void;
alertInTargetId(text: string | number, pageId: string): void;
closePageByPageName(pageName: string): void;
closePageByPageId(pageId: string): void;
getLastOpenPage(): IPage | null;
getLatestActivePage(): IPage | null;
getAllPages(): IPage[];
}
}
interface IPage {
name: string;
id: string;
index: number;
show: boolean;
}
interface IMsgData {
data: any;
page: IPage;
messageType: string | number;
messageId: string;
targetPageId?: string;
targetPageName?: string;
}
3.2 pageId 和 pageName
传入或生成的页面id和页面名称属性
3.3 postMessage 方法
function postMessage(data: any, messageType?: number | string): void;
import initMessager from 'cross-window-message';
const messager = initMessager('pageName', 'pageId');
messager.postMessage({
text: 'Hello World!'
})
向其他所有页面(包含自己)发送数据,第二个参数表示消息类型,可以为空
3.4 postMessageToTargetId 和 postMessageToTargetName
function postMessageToTargetId(targetPageId: string, data: any, messageType?: number | string): void;
function postMessageToTargetName(targetPageName: string, data: any, messageType?: number | string): void;
这两个方法用于向指定 pageId 或者 pageName 的页面定向发送数据,其他非目标页面不会收到消息
其他用法与 postMessage 一致
3.5 onMessage
function onMessage(fn: (msgData: IMsgData) => void): () => void;
interface IMsgData {
data: any; // postMessage 传入的data
page: IPage; // 消息来源页面的信息
messageType: string | number; // postMessage 传入的 messageType
messageId: string; // 生成的唯一消息id
targetPageId?: string; // 调用 postMessageToTargetId 时传入的 targetPageId 可以通过这个属性判断消息是否来自与 postMessageToTargetId 方法
targetPageName?: string; // 调用 postMessageToTargetName 时传入的 targetPageName 可以通过这个属性判断消息是否来自与 postMessageToTargetName 方法
}
interface IPage {
name: string; // 页面的名称
id: string; // 页面id
index: number; // 页面打开的次序
show: boolean; // 页面是否可见
}
import initMessager from 'cross-window-message';
const messager = initMessager('pageName', 'pageId');
messager.onMessage((msgData)=>{
console.log(msgData);
})
注册一个接收消息的事件
事件回调接收的参数是一个 IMsgData 类型
3.6 页面事件
function onUnload(func: (event: BeforeUnloadEvent) => void): () => void;
function onClick(func: (event: MouseEvent) => void): () => void;
function onShow(func: (event: Event) => void): () => void;
function onHide(func: (event: Event) => void): () => void;
分别用于监听页面的 beforeunload click visibilitychange 事件
参数与原生一致
3.7 工具方法
messager.method 对象上暴露了一些工具方法
import initMessager from 'cross-window-message';
const messager = initMessager('pageName', 'pageId');
messager.method.closeOtherPage()
closeOtherPage(): void; // 关闭其他所有页面
closeOtherSamePage(): void; // 关闭其他所有和当前页面pageName相同的页面
alertInTargetName(text: string | number, pageName: string): void; // 在目标pageName页面alert一条消息
alertInTargetId(text: string | number, pageId: string): void; // 在目标pageId页面alert一条消息
closePageByPageName(pageName: string): void; // 关闭所有目标pageName页面
closePageByPageId(pageId: string): void; // 关闭目标pageId页面
getLastOpenPage(): IPage | null; // 获取最新打开的页面
getLatestActivePage(): IPage | null; // 获取最新的活跃页面 (触发了click或者onshow事件的页面)
getAllPages(): IPage[]; // 获取所有打开的页面
3.8 版本
import initMessager from 'cross-window-message';
initMessager.version;