前言
通信过程描述:
- 父页面监听
message
(READY_IFRAME_DATA
) iframe
通知父页面可以发送数据(parent.postMessage
),同时监听message
- 父页面收到通知,开始发送数据(
iframe.postMessage
) iframe
收到数据(AS_IFRAME_DATA
)
数据通信使用
postMessage
/window.addEventListener('message')
的方式,通过指定type
来确定数据来源
注意
postMessage
/message
是在同一个window
配对的
数据传递的一些 type:
READY_IFRAME_DATA
: iframe作为通知父页面发送数据标志AS_IFRAME_DATA
: iframe作为接收数据来源标志FROM_IFRAME_DATA
: 父页面接收iframe传递数据
如果只需要父页面
->iframe
传递数据,只要前面两个type
就够了
iframe页面
注意,如果是传递登录态token,
iframe
的src
初始值应该是空的,避免页面加载太快,token
在传递过去之前就发出请求
接收数据
做了两件事:
parent.postMessage
通知父页面可以发送数据- 监听
message
,父页面通过iframe.postMessage
传递数据 - 将接收的数据存到
window
下,方便页面初始化的地方读取
写在html
文件script
标签内,尽量早的执行
<script>
/**
* 作为iframe时的一些处理
*/
if (window.parent) {
// 通知父页面传递数据
window.parent.postMessage({ type: 'READY_IFRAME_DATA' }, '*');
// 监听父页面传递的数据
window.addEventListener('message', function(e) {
if (e.data && e.data.type === 'AS_IFRAME_DATA') {
const messageData = e.data.data;
window.__as_iframe_data = messageData;
}
});
}
</script>
使用数据
比如在main.ts
入口或者App组件 mounted
执行方法initAsIframeData
// 作为ifrmae嵌入的数据处理
initAsIframeData() {
const iframeData = (window as any).__as_iframe_data;
if (iframeData) {
// 写入token到cookie
iframeData.token && cookie.set(TOKEN_NAME, iframeData.token);
}
}
父页面
数据通信
通过监听
iframe
页面window.onload
事件的方式会比较慢,使用框架的话可能会在框架mounted
之后触发,这样传递数据就没有作用了
做了两件事:
- 监听
message
,iframe
通过parent.postMessage
通知父页面可以发送数据 - 通过
iframe.postMessage
发送数据
发送数据
- 初始化
父页面在合适的时机初始化,传入iframe
元素及需要发送的数据
/**
* 初始化
* @param {*} iframe
* @param {*} data
*/
init (iframe, data) {
if (!iframe) {
console.warn('请确认iframe元素是否存在!');
return;
}
this.iframe = iframe;
this.messageData = data;
this.addListener();
},
- 发送数据
/**
* 发送数据
* @param {*} data
*/
sendData: function (data) {
const type = 'AS_IFRAME_DATA';
this.iframe.contentWindow.postMessage({ type, data }, '*');
},
- 整体代码
/**
* 与iframe内页面的数据通信处理
*/
const iframePageTools = {
iframe: null,
messageData: null,
/**
* 初始化
* @param {*} iframe
* @param {*} data
*/
init (iframe, data) {
if (!iframe) {
console.warn('请确认iframe元素是否存在!');
return;
}
this.iframe = iframe;
this.messageData = data;
this.addListener();
},
/**
* 发送数据
* @param {*} data
*/
sendData: function (data) {
const type = 'AS_IFRAME_DATA';
this.iframe.contentWindow.postMessage({ type, data }, '*');
},
listenerHandle: function (e) {
// 监听事件,iframe内页面需要调用
// window.parent.postMessage({ type: 'READY_IFRAME_DATA' });
if (e.data && e.data.type === 'READY_IFRAME_DATA') {
iframePageTools.sendData(iframePageTools.messageData);
}
},
addListener: function () {
window.addEventListener('message', this.listenerHandle);
},
removeListener: function () {
window.removeEventListener('message', this.listenerHandle);
},
};
最后
到此结束