https://www.jianshu.com/p/bc397045937e
https://segmentfault.com/a/1190000016258735
https://blog.csdn.net/tang_yi_/article/details/79401280
window.postMessage() 方法可以安全地實現跨源通信。通常,對於兩個不同頁面的腳本,只有當執行它們的頁面位於具有相同的協議(通常為https),端口號(443為https的默認值),以及主機 (兩個頁面的模數 Document.domain
設置為相同的值) 時,這兩個腳本才能相互通信。window.postMessage() 方法提供了一種受控機制來規避此限制,只要正確的使用,這種方法就很安全。
原理:
- 利用postMessage不能和服務端交換數據,只能在兩個窗口(iframe)之間交換數據
- 兩個窗口能通信的前提是,一個窗口以iframe的形式存在於另一個窗口,或者一個窗口是從另一個窗口通過window.open()或者超鏈接的形式打開的(同樣可以用window.opener獲取源窗口)
語法
otherWindow.postMessage(message, targetOrigin, [transfer]);
1.otherWindow
其他窗口的一個引用,比如iframe的contentWindow屬性、執行window.open返回的窗口對象、或者是命名過或數值索引的window.frames。
2.message
- 將要發送到其他 window的數據。它將會被 結構化克隆算法序列化。這意味着你可以不受什么限制的將數據對象安全的傳送給目標窗口而無需自己序列化。
3.targetOrigin
- 通過窗口的origin屬性來指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示無限制)或者一個URI。在發送消息的時候,如果目標窗口的協議、主機地址或端口這三者的任意一項不匹配targetOrigin提供的值,那么消息就不會被發送;只有三者完全匹配,消息才會被發送。這個機制用來控制消息可以發送到哪些窗口;例如,當用postMessage傳送密碼時,這個參數就顯得尤為重要,必須保證它的值與這條包含密碼的信息的預期接受者的origin屬性完全一致,來防止密碼被惡意的第三方截獲。 如果你明確的知道消息應該發送到哪個窗口,那么請始終提供一個有確切值的targetOrigin,而不是*。不提供確切的目標將導致數據泄露到任何對數據感興趣的惡意站點。
4.transfer
可選
-
是一串和message 同時傳遞的
Transferable
對象. 這些對象的所有權將被轉移給消息的接收方,而發送一方將不再保有所有權。
使用
1.父頁面向子頁面傳遞數據並監聽子頁面發送過來的信息
<template> <div class=""> <iframe id="test" ref="iframe" height="1000" width="100%" frameborder="no" scrolling="no" :src="src" /> <div @click="sendMessage">向iframe發送信息</div> </div> </template> <script> import { getToken, setToken } from '@/utils/auth' export default { components: {}, data() { return { src: 'https://ftctest.btonline365.com/html/Risk/model/model_list.html?token=' + getToken() } }, computed: {}, watch: {}, created() {}, mounted() { this.iframeInit() console.log(this.src) }, beforeCreate() {}, beforeMount() {}, beforeUpdate() {}, updated() {}, beforeDestroy() {}, destroyed() {}, activated() {}, methods: { iframeInit() { const iframe = this.$refs.iframe // 處理兼容問題 if (iframe.attachEvent) { // 監聽子級返回數據 window.attachEvent( 'onmessage', (e) => { // console.log("父級接收子級返回數據" + e.data); alert('iframe頁面token失效了啊啊啊啊啊') // setToken(JSON.parse(e.data)) // 外部vue向iframe內部傳數據 iframe.contentWindow.postMessage({ token: getToken() }, 'https://ftctest.btonline365.com/html/Risk/model/model_list.html') }, false ) } else { // 接受子級返回數據 window.addEventListener( 'message', (e) => { console.log(e.data) // alert('iframe頁面token失效了') // 外部vue向iframe內部傳數據 iframe.contentWindow.postMessage(JSON.stringify({ token: getToken() }), this.src) }, false ) } } } } </script>
2.子頁面監聽父頁面消息,並向父頁面發送數據
// 向父vue頁面發送信息 window.parent.postMessage({ cmd: 'returnHeight', params: { success: true, data: document.body.scrollHeight + 'px' } }, '*'); // 接受父頁面發來的信息 window.addEventListener("message", function(event){ var data = event.data; switch (data.cmd) { case 'getFormJson': // 處理業務邏輯 break; } });