1.背景
在公司低代码平台项目中, 有人封装了一个高度定制化的包, 但存在如下缺点:
-
- 高度定制化, 不支持功能和业务扩展
-
- 由于包封装原因, 业务代码在使用过程中紊乱分散, 不利于后续委会
-
- 当前业务中新增通信链路必须侵入npm包内, 增加调试成本
-
- 包内代码存在坏味道
common-postmessage具备业务通用的postMessage实现, 其内置单例模式和各种边界情况的兜底处理, 父子页面分别在初始化时输入策略模式, 则自动监听整条通信链路并根据通信数据触发对应的事件行为。
2.对外API说明
2-1.父页面API
/** 父页面 接口定义 */
export interface ParentWindowInterface<ParentPostAction extends ActionValType> {
/** 发送数据给子页面 */
postChildMesage(iframeName: string, data: PostMessageData<ParentPostAction>): void;
/** 获取当前页面下所有 Iframe 的初始化情况 */
getIframeInitMap(): any;
/** 记录当前页面下所有 Iframe 的初始化完成情况 */
updateIframeInitMap(iframeName: string): void;
/** 获取自定义集合 */
getCustomizedMap(): any;
/** 增量更新自定义集合 */
updateCustomizedMap(data: any): void;
}
/** 父页面 Props定义 */
export interface ParentWindowProps<ChildPostAction extends ActionValType> {
/** 父页面要监听message的策略模式对象 */
pageActionMap: PageActionMap<ChildPostAction>;
/** 父页面自定义配置, 如父页面postmessage事件等 */
customizedMap: any
}
2-2.子页面API
/** 子页面 接口定义 */
export interface ChildWindowInterface<ChildPostAction extends ActionValType> {
/** 发送数据给父页面 */
postFatherMesage(data: PostMessageData<ChildPostAction>): void;
/** 获取自定义集合 */
getCustomizedMap(): any;
/** 增量更新自定义集合 */
updateCustomizedMap(data: any): void;
}
/** 子页面 Props定义 */
export interface ChildWindowProps<ParentPostAction extends ActionValType> {
/** 子页面要监听message的策略模式对象 */
pageActionMap: PageActionMap<ParentPostAction>;
/** 子页面自定义配置, 如子页面postmessage事件等 */
customizedMap: any
}
3. 使用范例
父子页面使用的通用配置, 如下:
建议 :枚举均采用独一无二的字符串 区分 。
// common.ts
import { BaseActionCmd } from '@tencent/common-postmessage';
// BaseActionCmd 中定义了十数个字段, 可用于业务侧的父子页通用行为标识, 当此字段数量不够用时, 该包支持自定义枚举
// 建议:优先使用 BaseActionCmd, 根据业务需求赋予其命令不同含义 。业务侧自定义枚举采用独一无二的字符串区分。
// 业务侧自定义枚举: 子页面传递给父页面的事件命令
enum ChildPostAction {
/** 更新父页面的top值 */
UPDATE_PARENT_TOP = 'UPDATE_PARENT_TOP',
}
// 业务侧自定义枚举: 父页面传递给子页面的事件命令
enum ParentPostAction {
/** 更新子页面的bottom值 */
UPDATE_CHILD_BOTTOM = 'UPDATE_CHILD_BOTTOM',
}
在父页面中, 如下使用:
import { getParentWindowCtrl, ParentWindowProps } from '@/common-postmessage';
import { ChildPostAction, ParentPostAction } from './common';
// 业务侧自定义: 父页面通信事件集合 (父页面根据收到的子页面的数据, 触发对应的父页面事件)
const PARENT_ACTION_MAP = {
[ChildPostAction.UPDATE_PARENT_TOP]: () => {},
};
// 业务侧自定义: 父页面通信事件集合 (父页面根据收到的子页面的数据, 触发对应的父页面事件)
const PARENT_ACTION_MAP = {
[ChildPostAction.UPDATE_PARENT_TOP]: () => {},
};
/**
* 页面通信自定义业务配置
* @desc 可选填
* @desc 可以放一些父页面专用的配置项
*/
const INIT_CUSTOMIZED_MAP = {
/** 初始化数据 */
awaitInitData: '',
/** 发送数据 */
awaitPostData: '',
};
const configProps: ParentWindowProps<ChildPostAction> = {
pageActionMap: PARENT_ACTION_MAP,
customizedMap: INIT_CUSTOMIZED_MAP,
}
// App 页面初始化时: vue-mounted, react-didmount
getParentWindowCtrl<ChildPostAction, ParentPostAction>(configProps);
// 在别的页面调用时, 可无需挂在到 store 中, 直接调用即可获得单例
// 使用时一定要在 初始化 调用结束之后!!!
const parentWindow = getParentWindowCtrl();
在子页面中, 如下使用:
import { getChildWindowCtrl, ChildWindowProps } from '@/common-postmessage';
import { ChildPostAction, ParentPostAction } from './common';
// 业务侧自定义: 子页面通信事件集合 (子页面根据收到的父页面的数据, 触发对应的子页面事件)
const CHILD_ACTION_MAP = {
[ParentPostAction.UPDATE_CHILD_BOTTOM]: () => {},
};
/**
* 页面通信自定义业务配置
* @desc 可选填
* @desc 可以放一些子页面专用的配置项
*/
const INIT_CUSTOMIZED_MAP = {
/** 通知父页面, 当前scrolltop变化 */
postScrollTopCmd: () => {},
};
const configProps: ChildWindowProps<ParentPostAction> = {
pageActionMap: CHILD_ACTION_MAP,
customizedMap: INIT_CUSTOMIZED_MAP,
}
// App 页面初始化时: vue-mounted, react-didmount
getChildWindowCtrl<ChildPostAction, ParentPostAction>(configProps);
// 在别的页面调用时, 可无需挂在到 store 中, 直接调用即可获得单例
// 使用时一定要在 初始化 调用结束之后!!!
const childWindow = getChildWindowCtrl();

