父頁面iframe中的第三方子頁面跨域交互技術(shù)—postMessage實(shí)現(xiàn)方法
在web項(xiàng)目中通過iframe嵌入另一個(gè)第三方web項(xiàng)目,第三方web項(xiàng)目里點(diǎn)擊某個(gè)按鈕要實(shí)時(shí)調(diào)用web項(xiàng)目的全局函數(shù)打開某個(gè)全局彈窗或者進(jìn)行路由跳轉(zhuǎn),這時(shí)候兩個(gè)項(xiàng)目存在了數(shù)據(jù)交互,顯然違反了同源策略,在HTML5標(biāo)準(zhǔn)引入的window對(duì)象下的postMessage方法,可以允許來自不同源的腳本采用異步方式進(jìn)行有限的通信,可以實(shí)現(xiàn)跨文本檔、多窗口、跨域消息傳遞。
window.postMessage是HTML5中新增的一個(gè)API(不能低于IE8),postMessage方法允許來自不同源的腳本采用異步方式進(jìn)行有限的通信 ,使其可以實(shí)現(xiàn)跨文本檔、多窗口、跨域消息傳遞,這個(gè)API為 window 對(duì)象新增了一個(gè)window.postMessage方法,允許跨窗口通信,無論當(dāng)前兩個(gè)窗口否是同源。
postMessage傳遞消息
在 html5,window 對(duì)象上有一個(gè)方法叫做postMessage,與它的名字一樣,這個(gè)方法就是用來發(fā)送信息的,但是它只能用來在兩個(gè)窗口之間發(fā)送信息
發(fā)送消息方法的參數(shù)和使用
win.postMessage(data, origin) // win 這個(gè)參數(shù)為需要接受消息的 window 對(duì)象 // 當(dāng)我們通過 window.open() 打開一個(gè)新窗口時(shí),會(huì)返回一個(gè)新窗口的 window 對(duì)象,通過這個(gè)新窗口的 window 對(duì)象,就可以向新窗口發(fā)送消息 // 如果頁面中有 frame 時(shí),也可以通過這個(gè) frame 對(duì)象發(fā)送消息 // data 為我們想要發(fā)送的數(shù)據(jù),理論上 data 可以是任何可以被復(fù)制的數(shù)據(jù)類型,但是由于部分瀏覽器只支持傳輸 String 類型,所以傳輸?shù)臄?shù)據(jù)最好是通過 JSON.stringify() 序列化后再傳輸 // origin 為字符串,為目標(biāo)窗口的源,由 協(xié)議+ip/域名+端口號(hào) 組成 // 如果想要傳遞給任意窗口,可以將這個(gè)參數(shù)設(shè)置為 * ,為了安全起見,不建議設(shè)置為 * // 如果目標(biāo)窗口與當(dāng)前窗口同源,則設(shè)置為 /
接收消息方法的參數(shù)和使用
window.addEventListener('message', function (e) {...}) // 第一個(gè)參數(shù)為這個(gè)事件監(jiān)聽器的類型,'message' 表示會(huì)監(jiān)聽當(dāng)前窗口接收到的消息 // 第二個(gè)參數(shù)為接收到消息后的回調(diào)函數(shù),在回調(diào)函數(shù)中,我們可以對(duì)發(fā)送消息的源進(jìn)行一些驗(yàn)證,從而保證安全性 // 回調(diào)函數(shù)參數(shù) e 上有很多屬性,我們可以將其打印出來,其中 origin 表示發(fā)送消息窗口的源;source 屬性表示發(fā)送消息的窗口,通過 e.source == window.opener 可以判斷發(fā)送消息的窗口與打開當(dāng)前頁面的窗口是否為同一個(gè);data 屬性標(biāo)書傳遞過來的數(shù)據(jù)
使用場(chǎng)景
當(dāng)想要在Web頁面中嵌入一個(gè)來自其他站點(diǎn)的模塊或者“gadget”的時(shí)候,利用 postMessage() 和 message 事件實(shí)現(xiàn)的跨域消息傳遞是很有用的。
首先 gadget 的開發(fā)者可以將 gadget 內(nèi)容定義在一個(gè) HTML 頁面中,它負(fù)責(zé)監(jiān)聽 message 事件,并將它們分發(fā)給對(duì)應(yīng)的 js 函數(shù)去處理。然后,嵌入 gadget 的Web頁面就可以通過 postMessage() 方法傳遞消息來和 gadget 進(jìn)行交互了。
使用示例
加入有a.html和b.html兩個(gè)頁面,a.html是父頁面,b.html是子頁面,可以是同源同一個(gè)網(wǎng)站(網(wǎng)址一樣),也可以是不同源的跨域網(wǎng)站。
父級(jí)頁面給子級(jí)頁面?zhèn)鲄?/h3>
//a.html
<body>
<div class='body'>
<div class='left'>
<p>LEFT</p>
<button id='iframeEvent'>給子級(jí)頁面?zhèn)鲄?lt;/button>
</div>
<div class='right'>
<iframe id='ifrA' src="b.html" frameborder="0"
width='100%' height='100%'></iframe>
</div>
</div>
<script>
var ifr = document.getElementById('ifrA');
var send = document.getElementById('iframeEvent');
//父級(jí)頁面發(fā)送參數(shù)
send.addEventListener('click', function() {
var url = 'http://127.0.0.1:5500/b.html';//地址必須為服務(wù)器地址(本地文件打開無效)
var val = '我是父級(jí)頁面過來的參數(shù)';//傳遞的參數(shù)
ifr.contentWindow.postMessage(val, url)
}, false)
</script>
</body>
//b.html
<body>
<p class='title'>我是子級(jí)頁面</p>
<script>
window.addEventListener('message', function(event) {
var url = 'http://127.0.0.1:5500';//指定的源
if (event.origin != url) {//判斷是否來自指定源
return;
}
console.log(event.data);//讀取傳遞過來值
}, false)
</script>
</body>
//a.html <body> <div class='body'> <div class='left'> <p>LEFT</p> <button id='iframeEvent'>給子級(jí)頁面?zhèn)鲄?lt;/button> </div> <div class='right'> <iframe id='ifrA' src="b.html" frameborder="0" width='100%' height='100%'></iframe> </div> </div> <script> var ifr = document.getElementById('ifrA'); var send = document.getElementById('iframeEvent'); //父級(jí)頁面發(fā)送參數(shù) send.addEventListener('click', function() { var url = 'http://127.0.0.1:5500/b.html';//地址必須為服務(wù)器地址(本地文件打開無效) var val = '我是父級(jí)頁面過來的參數(shù)';//傳遞的參數(shù) ifr.contentWindow.postMessage(val, url) }, false) </script> </body>
//b.html <body> <p class='title'>我是子級(jí)頁面</p> <script> window.addEventListener('message', function(event) { var url = 'http://127.0.0.1:5500';//指定的源 if (event.origin != url) {//判斷是否來自指定源 return; } console.log(event.data);//讀取傳遞過來值 }, false) </script> </body>
子級(jí)頁面給父級(jí)頁面?zhèn)鲄?/h3>
//a.html
<body>
<div class='body'>
<div class='right'>
<iframe id='ifrA' src="b.html" frameborder="0"
width='100%' height='100%'></iframe>
</div>
</div>
<script>
//接送參數(shù)
window.addEventListener('message', function(e) {
var url = 'http://127.0.0.1:5500';
if (e.origin != url) {
return;
}
console.log(e.data);
}, false)
</script>
</body>
//b.html
<body>
<button class='childPage'>給父頁面?zhèn)鬟f參數(shù)</button>
<script>
//發(fā)送子級(jí)頁面的參數(shù)給父級(jí)頁面
var btnEvent = document.querySelector('.childPage');
var data = '我是子級(jí)頁面?zhèn)鬟f過來的參數(shù)';
btnEvent.addEventListener('click', function(e) {
window.parent.postMessage(data, 'http://127.0.0.1:5500/a.html')
}, false)
</script>
</body>
//a.html <body> <div class='body'> <div class='right'> <iframe id='ifrA' src="b.html" frameborder="0" width='100%' height='100%'></iframe> </div> </div> <script> //接送參數(shù) window.addEventListener('message', function(e) { var url = 'http://127.0.0.1:5500'; if (e.origin != url) { return; } console.log(e.data); }, false) </script> </body>
//b.html <body> <button class='childPage'>給父頁面?zhèn)鬟f參數(shù)</button> <script> //發(fā)送子級(jí)頁面的參數(shù)給父級(jí)頁面 var btnEvent = document.querySelector('.childPage'); var data = '我是子級(jí)頁面?zhèn)鬟f過來的參數(shù)'; btnEvent.addEventListener('click', function(e) { window.parent.postMessage(data, 'http://127.0.0.1:5500/a.html') }, false) </script> </body>
安全問題
如果你不希望從其他網(wǎng)站接收 message,請(qǐng)不要為 message 事件添加任何事件監(jiān)聽器。
如果你確實(shí)希望從其他網(wǎng)站接收message,請(qǐng)始終使用 origin 和 source 屬性驗(yàn)證發(fā)件人的身份。
當(dāng)你使用 postMessage 將數(shù)據(jù)發(fā)送到其他窗口時(shí),始終指定精確的目標(biāo) origin,而不是 *。
兼容性
所有主流瀏覽器(包括IE8)都支持。
到此這篇關(guān)于父頁面iframe中的第三方子頁面跨域交互技術(shù)—postMessage實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)iframe跨域postMessage內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript中5個(gè)重要的Observer函數(shù)小結(jié)
瀏覽器為開發(fā)者提供了功能豐富的Observer,本文主要介紹了JavaScript中5個(gè)重要的Observer函數(shù)小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01Typescript模塊的導(dǎo)入導(dǎo)出與繼承方式
這篇文章主要介紹了Typescript模塊的導(dǎo)入導(dǎo)出與繼承方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09利用函數(shù)的惰性載入提高javascript代碼執(zhí)行效率
在 addEvent 函數(shù)每次調(diào)用的時(shí)候都要走一遍,如果瀏覽器支持其中的一種方法,那么他就會(huì)一直支持了,就沒有必要再進(jìn)行其他分支的檢測(cè)了2014-05-05js實(shí)現(xiàn)帶三角符的手風(fēng)琴效果
本文主要介紹了js實(shí)現(xiàn)帶三角符手風(fēng)琴效果的實(shí)例。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-03-03詳解webpack打包第三方類庫(kù)的正確姿勢(shì)
這篇文章主要介紹了詳解webpack打包第三方類庫(kù)的正確姿,我們主要介紹了webpack.optimize.CommonsChunkPlu,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10Javascript學(xué)習(xí)筆記 delete運(yùn)算符
關(guān)于javascript的delete運(yùn)算符,MDN里有相關(guān)文檔。以下是我的學(xué)習(xí)筆記,更多是要關(guān)注特殊情況的使用和注意點(diǎn)。2011-09-09