Skip to main content

iframe 组件

1 说明

iframe 组件主要要用于嵌入第三方定制化页面,定制页面通过接入 gg-sdk,调用组件配置的资源。比如,想在页面上展示一张网络图片,可以在数据源中粘贴图片的链接。是这么使用的吗?

2 配置

2.1 数据源

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

支持相对 URL 和外部绝对 URL

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

相对 URL 配置,如下图

绝对 URL 配置,如下图

关闭预览,如下图

2.2 配置参数

这些参数的意思是什么?我添加了这么多参数是在哪里用?添加参数里的资源、页面、禁用分别是什么作用(比如我选择了数据库中的一个实体,这个组件会呈现什么内容?)

参数配置标签栏可以

  • 操作参数标签菜单

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

  • 添加新的参数标签页

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

  • 修改现有参数页

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

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

  • 删除现有参数页

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

  • 禁用现有参数页

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

2.3 样式

补充

2.4 可见性设置

具体描述请点击详情 查看通用的描述(详情

2.5 设计

具体描述请点击详情 查看通用的描述(详情

2.6 SDK 对接相关

2.6.1 gg-sdk

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

2.6.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.6.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);

};