简介
在大多情况下我们都尽可能避免使用iframe,它的问题很多,但是在一些业务场景下又不得不使用它。 在一些场景下需要主页面和iframe子页面交互,这时可以用 window.postMessage 去解决
window.postMessage
**window.postMessage() **方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。**window.postMessage() **方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。
从广义上讲,一个窗口可以获得对另一个窗口的引用(比如 targetWindow = window.opener),然后在窗口上调用 targetWindow.postMessage() 方法分发一个 MessageEvent ****消息。接收消息的窗口可以根据需要自由处理此事件 (en-US)。传递给 window.postMessage() 的参数(比如 message )将通过消息事件对象暴露给接收消息的窗口。
具体代码
主页面调用iframe
发送信息
postMessageIframe('changePage', 'ceshi11')
/**
* 向子集的iframe发送消息
* @param funcName 方法名
* @param param 参数
* @param iframeId iframe名字
*/
export const postMessageIframe = (funcName, param, iframeId = 'iframeId') => {
let iframe = document.getElementById(iframeId);
let msg = {
funcName,
param
}
iframe.contentWindow.postMessage(msg, "*");
}
接受信息
/**
* 监听用户页面传回的数据 并调用 iframe 页面方法
*/
window.addEventListener('message', (e) => {
let data = e.data;
let funcName = data.funcName;
let param = data.param;
console.log('父级调用 ,调用测试:')
console.log(e)
console.log(data)
// 调用 iframe 页面方法
// window[funcName](param);
})
iframe调用父级
发送信息
/**
* 调用父级方法
* @param funcName 方法名
* @param param 参数
*/
function callFuncInMain(funcName, data) {
let message = {
'funcName': funcName,// 所要调用父页面里的函数名
'param': data
}
// 向父窗体(用户主页面)发送消息
// 第一个参数是具体的信息内容,
// 第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送
window.parent.postMessage(message, '*');
}
父级主页面接受
// 添加全局消息监听
window.addEventListener('message', (e) => {
let data = e?.data;
let funcName = data?.funcName;
let param = data?.param;
if(!funcName) return
console.log('iframe 调用Vue ,调用测试:')
console.log(e)
console.log(data)
window[funcName](param)
})
常见问题
addEventListener 添加监听后的销毁需要用到 removeEventListener,removeEventListener 必须指定移除的函数
例子
必须指定声明函数
let btn = document.getElementById("myBtn");
btn.addEventListener("click", function () {
alert(this.id);
}, false);
btn.removeEventListener("click", function () { //无效!
alert(this.id);
}, false);
let btn = document.getElementById("myBtn");
let handler = function () {
alert(this.id);
};
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false); //有效!