一、汇总
网页和多标签tab的通讯:websocket、onStorage、sharedWorker、broadCast Channel、postMessage、cookie定时器轮询…
网页和iframe之间的通信:postMessage、broadCast Channel…
二、同源策略
三、webSocket (无跨域限制)
优点:无跨域限制
缺点:成本高
四、客户端存储
1、localStorage + onStorage
例子:
如果修改的值未发生改变,window.onstorage 事件将不会触发
2、定时器 + 客户端存储
例子:
缺点:
五、postMessage (无跨域限制)
例子:
index.html
<body>
<div>
<iframe src="./ifr.html" id="ifr" style="width:600px; height:300px"></iframe>
</div>
主窗口
<div>
<div>Message:</div>
<div id="messages"></div>
</div>
<script>
window.addEventListener("message", function (event) {
messages.innerHTML += `
<div>${event.data}</div>
`
})
setInterval(() => {
ifr.contentWindow.postMessage(`message from index.html, ${Date.now()}`)
}, 5000)
</script>
</body>
ifr.html
<body>
iframe窗口
<div>
<div>Message:</div>
<div id="messages"></div>
</div>
<script>
window.addEventListener("message", function (event) {
messages.innerHTML += `
<div>${event.data}</div>
`
})
setInterval(()=> {
window.parent.postMessage(`message from ifr.html, ${Date.now()}`)
}, 5000)
</script>
</body>
六、Broadcast Channel 事件广播 超级好用!!!
- 允许同源的不同浏览器窗口、Tab页、frame或者iframe下的不同文档之间相互通信
- 缺点:同源策略
核心代码:
例子:
<body>
<section>
<iframe src="./page1.html"></iframe>
<iframe src="./page2.html"></iframe>
</section>
</body>
<body>
<h3>Page 1</h3>
<section style="margin-top:50px; text-align: center">
<input id="inputMessage" value="page 1的测试消息" />
<input type="button" value="发送消息" id="btnSend" />
<section id="messages">
<p>收到的消息:</p>
</section>
</section>
<script>
var messagesEle = document.getElementById("messages")
var messageEl = document.getElementById("inputMessage")
var btnSend = document.getElementById("btnSend")
var channel = new BroadcastChannel("channel-BroadcastChannel")
channel.addEventListener("message", function (ev) {
var msgEl = document.createElement("p")
msgEl.innerText =
ev.data.date + " " + ev.data.from + ":" + ev.data.message
messagesEle.appendChild(msgEl)
})
btnSend.addEventListener("click", function () {
var message = messageEl.value
channel.postMessage({
date: new Date().toLocaleString(),
message,
from: "page 1"
})
})
</script>
</body>
<body>
<h3>Page 2</h3>
<section style="margin-top:50px; text-align: center">
<input id="inputMessage" value="page 2的测试消息" />
<input type="button" value="发送消息" id="btnSend" />
<section id="messages">
<p>收到的消息:</p>
</section>
</section>
<script>
var messagesEle = document.getElementById("messages")
var messageEl = document.getElementById("inputMessage")
var btnSend = document.getElementById("btnSend")
var channel = new BroadcastChannel("channel-BroadcastChannel")
channel.addEventListener("message", function(ev) {
var msgEl = document.createElement("p")
msgEl.innerText = ev.data.date + " " + ev.data.from + ":" + ev.data.message
messagesEle.appendChild(msgEl)
})
btnSend.addEventListener("click", function() {
var message = messageEl.value
channel.postMessage({
date: new Date().toLocaleString(),
message,
from: "page 2"
})
})
</script>
</body>
七:MessageChannel (无跨域限制)
Channel Messaging
API 的MessageChannel
接口允许我们创建一个新的消息通道,并通过它的两个MessagePort属性发送数据- 缺点: 需要先创建联系
核心代码:
例子:
<body>
<iframe id="ifr" src="./ifr.html" style="width:600px; height:300px"></iframe>
<div>主窗口</div>
<div>
<div>Message:</div>
<div id="messages"></div>
</div>
<script>
const channel = new MessageChannel()
var ifr = document.querySelector('iframe')
ifr.onload = function () {
ifr.contentWindow.postMessage('__init__', '*', [channel.port2])
}
// 监听消息
channel.port1.onmessage = onMessage
function onMessage(e) {
messages.innerHTML += `
<div>${event.data}</div>
`
}
// 轮询发送
setInterval(function(){
channel.port1.postMessage(`message from index.html, ${Date.now()}`)
}, 5000)
</script>
</body>
<body>
iframe窗口
<div>
<div>Message:</div>
<div id="messages"></div>
</div>
<script>
window.addEventListener("message", function (event) {
if (event.data === "__init__") {
initChannel( event.ports[0])
}
})
function initChannel(port) {
port.onmessage = function (event) {
messages.innerHTML += `
<div>${event.data}</div>
`
port.postMessage(`message from the iframe, ${Date.now()}`);
}
}
</script>
</body>
八、SharedWorker
SharedWorker
是Web Worker
的一种, 可单独开启一个进程,用于同域页面通讯Web Worker
可开启子进程执行JS,但不能操作DOM- 缺点:兼容性、同源策略
例子: