我有两个来源不同的网站。让它成为 foo.com 和 bar.com。网站 foo.com 通过
BroadcastChannel
发送带有 'payment-info'
名称的消息。我还有一个 iframe,托管在 foo.com 上,它内置于 bar.com 中。这是 iframe 代码:
<html><head><script type="text/javascript">
(function () {
const bc = new BroadcastChannel('payment-info');
bc.addEventListener('message', (m) => {
const data = JSON.parse(m.data);
data.channel = 'payment-info';
if (window.top !== window) {
window.top.postMessage(JSON.stringify(data), '*');
}
});
})();
</script></head><body></body></html>
因此 iframe 订阅
'payment-info'
广播频道,当它触发时,iframe 会向其父窗口(又名 bar.com)发布一条消息,其中包含一些信息。
在 bar.com 一侧,我只是监听“message”事件并使用 JSON.parse 调用“receiveMessage”函数
window.addEventListener('message', function (message) {
receiveMessage(message);
});
预计它可以在我的网站 bar.com 的所有浏览器中运行。它在 Safari 和 Firefox 中不起作用,但在 Chrome 中起作用。
我将 index.html、index2.html 和 iframe.html 几个文件中的代码组合在一起,用于在一个文件中进行本地测试。 index.html 和 iframe.html 被认为来自一个来源,而 index2.html 来自另一个来源。不幸的是,如果没有两个具有不同域的不同服务器,就不可能像普通 HTML/JS 一样测试它
<!--INDEX CODE-->
<!doctype html>
<html lang="">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:title" content="">
<meta property="og:type" content="">
<meta property="og:url" content="">
<meta property="og:image" content="">
<meta name="theme-color" content="#fafafa">
</head>
<body>
<p>index page</p>
<a href="/page.html">link</a>
<script>
let i = 0;
const bc = new BroadcastChannel('payment-page');
function sendItem() {
i+=1;
const message = '{"message":"Hello from the new window!"}';
if (window.opener) window.opener.postMessage(message, '*');
const data = { message: `Hello from broadcast ${i}` };
console.log(JSON.stringify(data));
bc.postMessage(JSON.stringify(data))
console.log(message)
}
</script>
<button onclick="sendItem()">send item</button>
</body>
</html>
<!--END OF INDEX CODE-->
<!--IFRAME CODE-->
<html><head><script type="text/javascript">
(function () {
const bc = new BroadcastChannel('payment-page');
console.log('broadcast channel is created', bc)
bc.addEventListener('message', (m) => {
console.log('proxy: receive message ', m);
const data = JSON.parse(m.data);
data.channel = 'payment-page';
if (window.top !== window) {
// Inside iframe. Proxy to top.
console.log('proxy: send to parent');
window.top.postMessage(JSON.stringify(data), '*');
}
});
})();
</script></head><body></body></html>
<!--END OF IFRAME-->
<!--INDEX2 CODE-->
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<iframe
width="100"
height="100"
src="http://domain-1.com:3000//iframe.html"
></iframe>
<script>
window.addEventListener('message', function (message) {
if (message.data && typeof message.data === 'string') {
console.log(JSON.parse(message.data))
}
});
</script>
</body>
</html>
广播通道仅适用于同源页面之间。
广播通道 API 允许浏览器之间进行基本通信 上下文(即窗口、选项卡、框架或 iframe)和工作人员 同源。
https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API