iframe通过postMessage跨域通信,一看就懂!

74 阅读1分钟

背景

web端页面加载课件组制作的动画页面,web端需要把参数传递到iframe里面,告诉课件组同学具体加载哪个动画页面。这种情况下很自然想到用iframe方式加载动画页面,然后通过postMessage通信传递参数。

iframe优缺点

  • 会阻塞主页面的onload事件

解决方案: 动态生成iframe,在主页面加载完成后去生产iframe加载,从而避免阻塞的影响

  • 对SEO不友好

虽然iframe有缺点,但是在某些特定场景下,也可以发挥不错的作用。

postMessage

定义

postMessage() 方法用于安全地实现跨源通信。

语法

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

用法

标题说明
otherWindow其他窗口的一个引用,比如 iframe 的 contentWindow 属性、执行 window.open 返回的窗口对象、或者是命名过或数值索引的 window.frames。
message将要发送到其他 window的数据。
targetOrigin指定哪些窗口能接收到消息事件,其值可以是 *(表示无限制)或者一个 URI。
transfer可选,是一串和 message 同时传递的 Transferable 对象。这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

示例

主页面代码

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>主页面</title>
</head>

<body>
    <h1>主页面</h1>
    <iframe id="child" src="./iframe.html"></iframe>
    <div>
        <h2>主页面接收消息区域</h2>
        <span id="message"></span>
    </div>
</body>
<script>
    window.onload = function () {
        document.getElementById('child').contentWindow.postMessage("我是主页面哦", "http://localhost:5000")
    }
    window.addEventListener('message', function (event) {
        document.getElementById('message').innerHTML = "收到" + event.origin + "消息:" + JSON.stringify(event.data);
    }, false);
</script>

</html>

iframe页面代码

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>子页面</title>
</head>

<body>
    <h2>子页面</h2>
    <div>
        <h3>接收消息区域</h3>
        <span id="message"></span>

        <button onclick="send()">发送消息</button>
    </div>
</body>
<script>
    window.addEventListener('message', function (event) {
        if (window.parent !== event.source) return
        document.getElementById('message').innerHTML = "收到" + event.origin + "消息:" + JSON.stringify(event.data);
    }, false);

    function send() {
        top.postMessage({ type: 'focus' }, "http://localhost:5000")
    }
</script>

</html>

演示效果

正确演示.gif

如果我们把postMessage第二个参数端口改成5001,这时候页面加载完成iframe里面是接收不到主页面发送的消息,点击iframe的按钮也无法发送消息给主页面。

错误演示.gif