今天要來筆記一下一個可能是月經題,我有一個 parent.html 裡面嵌入了一個 son.html 這兩個位處於不同的 domain ,以前的年代可以很簡單的在 parent.html 裡面呼叫
son.html 裡面寫的 javascript function ,但是現在總是會出現..
Uncaught DOMException: Blocked a frame with origin "https://domain.com" from accessing a cross-origin frame.

1. 先敘述一下,我是要用 parent.html 呼叫 son.html 分別為 FuncA , FuncB 的兩個不同的 function ,並且我是需要取得回應值的。
2. 整理一下觀念,基本上現在要寫這樣的行為 其實是透過 postMessage 來做到 ,但是這觀念跟以前有點不一樣,傳統你會想成 , parent.html 呼叫 son.html 的 FuncA
,之後得到答案,但是現在思考的點應該是 parent.html 透過 postMessage 呼叫 son.html 的 FuncA ,之後 son.html 執行之後要透過 postMessage 去呼叫 parent.html
並且告訴他結果.
3. 還有一點該注意的,我這案例其中我規劃透過 postMessage 傳遞的時候我制定一個物件,其中包含 SourceType , Content , Func 。 SourceType
這邊主要判斷是不是自己寫的 程式來呼叫,因為我 Chrome 有裝一些數字錢包的外掛,它們也都是透過 postMessage 來 呼叫 function ,這就導致一堆呼叫進來的東西。Content 就是我要傳遞的資料,Func
就是判斷 呼叫哪一個 function
Source Code parent.htm:
<script src='https://code.jquery.com/jquery-3.6.0.min.js'></script>
<iframe src="https://localhost:44344/son.html" frameBorder="0" style="width:100%;height:100px"
id="codeMain"></iframe>
<button type="button" id="btnA">
test1
</button>
<button type="button" id="btnB">
test2
</button>
<script>
var iframeObj=document.getElementById("codeMain").contentWindow;
$('#btnA').click(function () {
var data = {};
//SourceType 帶入 DMIXEDITOR 代表是我們自己傳遞的
data.SourceType = 'DMIXEDITOR';
//主要傳遞的資料
data.Content = 'HELLO';
//給son做判別·要呼叫的是 FuncA
data.Func = 'FUNCA';
//關鍵是後面的要帶入'*'
iframeObj.postMessage(data, '*');
});
$('#btnB').click(function () {
var data = {};
data.SourceType = 'DMIXEDITOR';
data.Content =2;
data.Func = 'FUNCB';
document.getElementById("codeMain").contentWindow.postMessage(data, '*');
});
function receiveMessage(e) {
//判斷從 son 回 call 回來的地方
if (!e.data.hasOwnProperty('SourceType')) {
} else {
//是我族類我才執行呼叫
if (e.data.SourceType == 'DMIXEDITOR') {
alert(JSON.stringify(e.data));
}
}
}
// 監聽 message 事件
window.addEventListener('message', receiveMessage, false);
</script>
Source Code son.html:
<script>
function receiveMessage(e) {
if (!e.data.hasOwnProperty('SourceType')) {
} else {
//是我族類我才呼叫
if (e.data.SourceType === 'DMIXEDITOR') {
//判斷 是 FUNCA 就 執行 FuncA 要做的
if (e.data.Func === 'FUNCA') {
var data = {};
data.SourceType = 'DMIXEDITOR';
//加一點料證明 son 被呼叫過
data.Content = e.data.Content + " -CALLED_IFRAME_FUNCA";
//回傳給 parent.html
parent.postMessage(data, '*');
}
if (e.data.Func === 'FUNCB') {
var data = {};
data.SourceType = 'DMIXEDITOR';
data.Content = (e.data.Content += 99);
parent.postMessage(data, '*');
}
}
}
}
// 監聽 message 事件
window.addEventListener('message', receiveMessage, false);
</script>
大概就是這樣,紀錄一下,這裡面比較 tricky 的就是 domain 的部分要帶入 '*' 之前我乖乖地填寫 domain 結果我在 jsfiddle 上面測試都沒有過..
紀錄一下給需要的人..
jsfiddle 屍體 : https://jsfiddle.net/no2don/pfdtz7yk/31/
reference :
https://rockjins.js.org/2017/05/05/2017-05-05-iframe-cross-domain-Communication/
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage