iframe和主页面交互

861 阅读2分钟

简介

在大多情况下我们都尽可能避免使用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 必须指定移除的函数

image.png

例子

必须指定声明函数

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); //有效!