iframe的父子页面通信

作者: 麦西的西 | 来源:发表于2022-05-13 23:45 被阅读0次

    平时工作中有时会遇到页面嵌套的情况,一般是用iframe解决。那么,两个页面如何通信呢?下面分两种情况进行:

    一、父子页面同源的情况

    现在有两个不同源的iframe嵌套页面,父页面parent.html,子页面child.html,二者代码如下:

    // parent.html
    // ...
    <iframe
      id='testIframe'
      name='test'
      src='./child.html'
      frameborder='0'
      scrolling='no'>
    </iframe>
    
    <script type="text/javascript">
        function parentConsole(data) {
            console.log(data)
        }
    </script>
    // ...
    
    // child.html
    // ...
    <script type="text/javascript">
        function childConsole(data) {
            console.log(data)
        }
    </script>
    // ...
    

    1. 父页面调用子页面方法

    可以通过iframe的id或者name属性拿到iframe的window对象,然后直接调用子页面方法即可。我们把需要发送给子页面的信息放到方法childConsole里。如下:

    var iframeDom = document.getElementById('testIframe');
    // 需要等iframe加载完成后执行,不然有可能会报错
    iframeDom.onload = function () {
        var data = 'hello, child!';
        iframeDom.contentWindow.childConsole(data);
    }
    

    var iframeDom = document.getElementById('testIframe');
    iframeDom.onload = function () {
        var data = 'hello, child!';
        test.window.childConsole(data);
    }
    

    2. 子页面调用父页面方法

    可以通过window.top或者window.parent拿到父页面的window对象。然后直接调用父页面的方法即可。同样,把需要发给父页面的信息放到方法parentConsole里。如下:

    var data = 'hello, parent!';
    window.top.parentConsole(data); // 或者使用window.parent.parentConsole(data)也行
    

    二、父子页面跨域的情况

    可以通过postMessage来实现通信。

    otherWindow.postMessage(message, targetOrigin, [transfer]);
    

    其中的参数:
    otherWindow
    目标窗口。比如 iframe 的 contentWindow 属性
    message
    将要发送到其他 窗口 的数据。
    targetOrigin
    目标窗口的域。其值可以是字符串"*"(表示无限制)或者一个 URI。不提供确切的 targetOrigin 将导致数据泄露到任何对数据感兴趣的恶意站点。

    现在有两个不同源的iframe嵌套页面,父页面http://127.0.0.1:8001/parent.html,子页面http://127.0.0.1:8002/child.html(本地分别对两个html起了两个服务),其中父页面嵌套部分代码如下:

    // http://127.0.0.1:8001/parent.html
    <iframe
      id='testIframe'
      name='test'
      src='http://127.0.0.1:8002/child.html'
      frameborder='0'
      scrolling='no'>
    </iframe>
    

    1. 父页面发送信息,子页面接收信息

    // http://127.0.0.1:8001/parent.html
    // 父页面发送信息
    document.getElementById('testIframe').onload = function () {
        test.window.postMessage('hello, child!', 'http://127.0.0.1:8002');
    }
    
    // http://127.0.0.1:8002/child.html
    // 子页面接收信息
    window.addEventListener('message', e => {
        // 通过origin对消息进行过滤,避免遭到XSS攻击
        if (e.origin === 'http://127.0.0.1:8001') {
            console.log(e.origin) // 父页面所在的域
            console.log(e.data)  // 父页面发送的消息, hello, child!
        }
    }, false);
    

    2. 子页面发送信息,父页面接收信息

    // http://127.0.0.1:8002/child.html
    window.top.postMessage('hello, parent!', 'http://127.0.0.1:8001');
    
    // http://127.0.0.1:8001/parent.html
    window.addEventListener('message', e => {
        // 通过origin对消息进行过滤,避免遭到XSS攻击
        if (e.origin === 'http://127.0.0.1:8002') {
            console.log(e.origin) // 子页面所在的域
            console.log(e.data)  // 子页面发送的消息, hello, parent!
        }
    }, false);
    

    通过postMessagewindow.addEventListener('message', e => { ... })配合使用,我们就能够完成跨域iframe父子页面的通信。
    当然对于同源的iframe父子页面也可以采用postMessage的方式来发送接收信息。

    参考资料:
    postMessage APIhttps://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
    iframe跨域通信(postMessage)https://juejin.cn/post/6844904120680185869

    相关文章

      网友评论

        本文标题:iframe的父子页面通信

        本文链接:https://www.haomeiwen.com/subject/bveeurtx.html