Skip to main content

iframe 组件

1 说明

iframe 组件主要要用于嵌入第三方定制化页面,定制页面通过接入 gg-sdk,调用组件配置的资源。

2 配置

2.1 数据源

数据源 URL 支持配置域名 URL 或者配置表达式(通过变量拼接 URL)

支持相对 URL 和外部绝对 URL

预览开关可以控制 iframe 编辑态是否打开配置的网页

相对 URL 配置,如下图

绝对 URL 配置,如下图

关闭预览,如下图

2.2 配置参数

参数配置标签栏可以

  • 操作参数标签菜单

鼠标悬浮或在标签尾部的“...”,会出现参数配置的菜单列表

  • 添加新的参数标签页

点击 添加参数 按钮,弹窗中输入标签名,可选择是否禁用,点击保存即可创建新的标签页

  • 修改现有参数页

点击 修改 按钮,可在弹窗中修改参数信息

点击 保存 按钮,即可完成修改

  • 删除现有参数页

点击 删除 按钮,即可删除参数

  • 禁用现有参数页

点击 禁用 按钮,即可禁用参数

2.3 SDK 对接相关

2.3.1 gg-sdk

第三方定制页接入需要使用 gg-sdk,具体文件可在模板项目中获取(https://gitlab.xuelangyun.com/cli-template/frame-project-template

2.3.2 使用方式

在定制项目中,需要使用注册函数 registerIframeLintenerInner 注册监听,返回值中 callCommand 为调用指令的函数,removeListener 为移除监听的函数

在 vue 项目中建议将监听的注册卸载放在 vue 的页面挂载卸载回调中,防止重复切换页面导致重复监听

let callCmd;
onMounted(() => {
const { callCommand, removeListener } = registerIframeLintenerInner();
onUnmounted(removeListener);
callCmd = callCommand;
});

const clickItem = ({ cmd, params, title }) => {
if (!callCmd) {
return;
}
console.log(`触发外部gg ${title} 指令 ${cmd}`);
callCmd(cmd, params, (data) => {
console.log(`外部gg返回 ${title} 指令 ${cmd} 结果`, data);
// alert(JSON.stringify(data));
});
};

注册监听返回的 callCommand 函数有三个入参

第一个入参为指令名称,目前支持如下指令

// 指令名称
export const COMMAND_NAME = {
OPEN_PAGE: 'OPEN_PAGE', // 打开页面
CLOSE_PAGE: 'CLOSE_PAGE', // 关闭页面
RESET_FORM: 'RESET_FORM', // 重置表单
COMMON_ACTION: 'COMMON_ACTION', // commonAction
CALL_MICROFLOW: 'CALL_MICROFLOW', // 微流调用
CONTEXT_DATA: 'CONTEXT_DATA', // 上下文数据
REFRESH_PAGE: 'REFRESH_PAGE', // 刷新页面
GET_PAGEPKID: 'GET_PAGEPKID' , // 获取页面主键id
};

第二个入参为指令所需的参数,其中必须包含 resourceName 字段,即配置参数中配置的参数名称

第三个入参为调用指令的结果回调

其实 postMessage 方法本身只是 Windows API 提供的实现跨源通信的 api,本身是无法关联结果返回的,gg-sdk 通过约定消息结构,在消息体中加入 msgId 唯一标识,共工内部接收到指令处理获取结果后,会将结果带上 msgId,gg-sdk 通过 msgId 获取记录的回调函数,并以结果为入参执行

2.3.3 源代码

以下是 gg-sdk 源代码

const listenerType = 'message';

const guid = (prefix = '') => {
return (
prefix +
'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
})
);
};
// 获取url origin
const getUrlOrigin = (url) => {
return (/^https?:\/\/[\w-.]+(:\d+)?/i.exec(url) || [''])[0];
};

const log = (...args) => {
console.log('gg-sdk', ...args);
};

// iframe嵌入类型
const FRAME_TYPE = {
IFRAME_IN_GG: 'IFRAME_IN_GG', //共工内嵌iframe
GG_IN_IFRAME: 'GG_IN_IFRAME', // 第三方内嵌共工
};

// 通用iframe消息监听
function registerLintener(frameType, targetOrigin = '*', iframeRef?) {
const messageCBMap = {};
const callCommand = (cmd, data, cb?) => {
const msgId = guid('mid');
cb && (messageCBMap[msgId] = cb);
let postWindow = window.parent;
if (iframeRef?.value) {
postWindow = iframeRef?.value?.contentWindow;
}
postWindow.postMessage({ frameType, cmd, msgId, data }, targetOrigin);
};
const listenerCB = (e) => {
const { msgId, data } = e.data;
const cmdCB = messageCBMap[msgId];
if (cmdCB) {
cmdCB(data);
}
};

const removeListener = () => {
log(`removeListener ${frameType} ${targetOrigin}`);
window.removeEventListener(listenerType, listenerCB);
};
window.addEventListener(listenerType, listenerCB, false);
return { callCommand, removeListener };
}

// 指令名称
export const COMMAND_NAME = {
OPEN_PAGE: 'OPEN_PAGE', // 打开页面
CLOSE_PAGE: 'CLOSE_PAGE', // 关闭页面
RESET_FORM: 'RESET_FORM', // 重置表单
COMMON_ACTION: 'COMMON_ACTION', // commonAction
CALL_MICROFLOW: 'CALL_MICROFLOW', // 微流调用
CONTEXT_DATA: 'CONTEXT_DATA', // 上下文数据
REFRESH_PAGE: 'REFRESH_PAGE', // 刷新页面
};

// 被共工内嵌的第三方页面使用
export const registerIframeLintenerInner = () => {
log('注册iframe消息监听 inner');
const frameType = FRAME_TYPE.IFRAME_IN_GG;
return registerLintener(frameType);
};

// 第三方内嵌共工页面使用
export const registerIframeLintenerOuter = (iframeRef, url) => {
log('注册iframe消息监听 outer');
const targetOrigin = getUrlOrigin(url);
const frameType = FRAME_TYPE.GG_IN_IFRAME;
return registerLintener(frameType, targetOrigin, iframeRef);
};

2.4 其他配置

可见性请参考可见性/禁用性设置

样式相关请参考样式配置

点击事件功能配置请参考事件

高级功能请参考高级函数