什麼是iframe?
iframe 元素會創建包含另外一個文檔的內聯框架(即行內框架)。
什麼是postMessage?
window.postMessage() 方法可以安全地實現跨源通信。通常,對於兩個不同頁面的腳本,只有當執行它們的頁面位於具有相同的協議(通常爲https),端口號(443爲https的默認值),以及主機 (兩個頁面的模數 Document.domain
設置爲相同的值) 時,這兩個腳本才能相互通信。window.postMessage() 方法提供了一種受控機制來規避此限制,只要正確的使用,這種方法就很安全。
使用場景:
在一個項目的頁面中嵌入另一個項目的頁面,需要實現父子,子父頁面的通信。
1.嵌入頁面
iframe使用如下(端口爲8080):
<iframe id="myframe" name="myframe" :src="src" ref="iframe" scrolling="no" width="350px" height="350px" frameborder="0"></iframe>
在data中定義src引入端口號爲8081的頁面:
src:"http://127.0.0.1:8081/#/Login",
那麼問題就來了,嵌入的登錄模塊屬於子頁面(另一個項目,端口號8081)的東西,如何能讓我自己的頁面知道用戶點擊了藍色按鈕,達到登錄後隱藏登錄框的效果呢?在這裏,postMessage就派上了用場。
2.postMessage實現父子頁面通信
window.postMessage中的window在iframe中是指什麼呢?請看語法。
我們首先要獲取到iframe的contentWindow屬性放到mounted這個鉤子函數中。
mounted() {
this.iframeWin = this.$refs.iframe.contentWindow;
},
目標源寫成 * ,具備了兩個必要參數,我們就可以開始使用postMessage了。
一、子頁面向父頁面傳值
在這個項目中,我需要在點擊login按鈕(子頁面),並且登陸成功後在父頁面中隱藏登錄模塊。
我的父頁面如何才能知道用戶點擊了子頁面的按鈕?
postMessage只是一個溝通的橋樑。
子頁面說話,父頁面需要聽到。所以我們在父頁面的mounted函數中寫一個監聽。
mounted() {
window.addEventListener('message', this.handleMessage);
this.iframeWin = this.$refs.iframe.contentWindow;
},
下面爲完整代碼
子頁面代碼:
submit() {
// 向父vue頁面發送信息
window.parent.postMessage({
data: {
code:"success",
test:"我是子頁面的test!"
}
}, '*');
}
父頁面代碼:
<div class="login" v-if="!loginStatus">
<iframe id="myframe" name="myframe" :src="src" ref="iframe" scrolling="no" width="350px" height="350px" frameborder="0"></iframe>
</div>
methods: {
handleMessage (event) {
const data = event.data.data
if(data.code === "success"){
alert(data.test)
}
}
}
mounted() {
window.addEventListener('message', this.handleMessage);
this.iframeWin = this.$refs.iframe.contentWindow;
},
效果:
一、父頁面向子頁面傳值
代碼如下:
父頁面代碼:
sendMessage () {
// 外部vue向iframe內部傳數據
this.iframeWin.postMessage({
cmd: 'success',
data: "我是來自父頁面的data!"
}, '*')
子頁面監聽同理。