轉(zhuǎn)載請(qǐng)注明出處,點(diǎn)擊此處 查看更多精彩內(nèi)容。
前置知識(shí)點(diǎn): 同源策略 & 跨域
iframe 跨域
由于同源策略的限制,使用 iframe 標(biāo)簽引入非同源的資源,在外部操作 iframe 中的 DOM 元素將會(huì)被瀏覽器阻止并報(bào)錯(cuò)。
假設(shè)有兩個(gè)域名:blog.sch.com、game.sch.com。
在 blog 的頁面中加載 game 的頁面,并操作其中的 DOM 元素。
<body>
<div>This is outside window.</div>
<iframe src="https://game.sch.com"></iframe>
<script>
const frame = document.querySelector('iframe')
const frameDoc = frame.contentWindow.document
// 操作非同源的 iframe 中的 DOM 元素
frameDoc.body.innerHTML = 'This is iframe'
</script>
</body>
瀏覽器報(bào)錯(cuò)如下:
Uncaught DOMException: Blocked a frame with origin "https://game.sch.com" from accessing a cross-origin frame.
解決方案1:降域
降域是通過將不同域的 document.domain 指定為其共同父域從而使其同源的跨域解決方案。
blog.sch.com、game.sch.com 具有共同的父域 sch.com。
那么將兩個(gè)域名下的頁面的域修改為 sch.com 即可解決跨域問題。
document.domain = 'sch.com'
注意事項(xiàng):
-
document.domain指定的域必須為當(dāng)前域或者其父域。 - 子域與父域跨域時(shí),父域也必須指定
document.domain。
缺點(diǎn):只能用在具有相同父域的情況下。
那么當(dāng)兩個(gè)主域名完全不同時(shí),應(yīng)該怎么辦呢?這就要用到 postMessage 了。
解決方案2:postMessage
postMessage 是 HTML5 中新增的函數(shù),可以用來向 window 發(fā)送消息。
window.postMessage(message, targetOrigin)
message 是要發(fā)送的消息(可以是對(duì)象)。
targetOrigin 的值可以是 * 或者一個(gè) URI,用來指定可以接收該消息的域,* 表示可以發(fā)送到任意 window,如果 window 的域和 targetOrigin 不配,將不會(huì)發(fā)送該消息。
而有發(fā)送就會(huì)有接收,否則沒有任何意義。我們可以通過向 window 添加 message 事件監(jiān)聽器獲取發(fā)送的消息。
window.addEventListener('message', (event) => {
const { origin, source, data } = event
})
origin 是消息發(fā)送者的域,可以驗(yàn)證消息的發(fā)送者是否可被信任。
source 是消息發(fā)送者的 window 對(duì)象,可以使用 source.postMessage 向發(fā)送者回傳消息。
data 是消息內(nèi)容。