最近在公司專案學到了滿好用的功能 postMessage,當今天使用到跨視窗 iframe 或是 openWindow,原本 parent 頁面需要傳遞訊息給內頁 iframe 或是 tab 頁,就可以利用 postMessage 來傳遞資料。接下來會建立 demo 頁面,介紹一下 iframe 跟 window open 的使用方法。
window.postMessage() 方法被調用時,會在所有頁面腳本執行完畢之後
(e.g., 在該方法之後設置的事件、之前設置的timeout 事件,etc.)
向目標窗口派發一個 MessageEvent 消息。
該MessageEvent消息有四個屬性需要注意:
message 屬性表示該message 的類型;
data 屬性為 window.postMessage 的第一個參數;
origin 屬性表示調用 window.postMessage() 方法時調用頁面的當前狀態;
source 屬性記錄調用 window.postMessage() 方法的窗口信息。
window postMessage 介紹
postMessage 的調用方式 => targetWindow.postMessage(message, targetOrigin, [transfer]),targetWindow 會是某個窗口,targetOrigin 則是指定可傳遞的端口網域,transfer 是一串和 message 同時傳遞的 Transferable 對象。
targetWindow 可設定目標 :
- Window.open
- Window.opener
- HTMLIFrameElement.contentWindow (embedded iframe ),
- Window.parent ( parent window embedded iframe)
- Window.frames + an index value (named or numeric).
window open demo page
首先要建立送出訊息跟接受訊息的頁面,送出訊息頁面主要做兩件事情,開啟視窗並指定為變數、向剛剛開啟視窗頁面送出訊息。javascript 沒有特別難度,所以就直接看我建立好的頁面,底下是處理的 html 還有 javascript。
範例 :
- 使用步驟 先點選開啟視窗
- 輸入隨意字串
- 點選送出按鈕
ps.分頁切換需要用瀏覽器 app safari、chrome
Source : Open Window Demo Page
send.html
<!DOCTYPE html>
...
<h1 class="cover-heading">HTML send Post Message demo sample.</h1>
<p class="lead">
<button id="openWindow" type="button" class="btn btn-info">開啟視窗</button>
</p>
<div class="input-group">
<input type="text" id="messageText" class="form-control" placeholder="輸入訊息">
<div class="input-group-append">
<button id="postWindow" class="btn btn-info btn-outline-secondary" type="button">送出訊息</button>
</div>
</div>
...
<script>
// 建立變數
var createWindow;
document.getElementById('openWindow').addEventListener('click',function(e){
// 將變數 assign window open 物件
createWindow = window.open("./receive.html");
});
document.getElementById('postWindow').addEventListener('click',function(e){
sendMsg();
});
function sendMsg() {
var message = document.getElementById("messageText").value;
var domain = window.location.origin;
// post message
createWindow.postMessage(message, domain);
// focus windowOpen
createWindow.focus();
document.getElementById("messageText").value = '';
}
</script>
...
</html>
recevie.html
<!DOCTYPE html>
...
<p class="lead">
<h2 id="response"></h2>
</p>
...
<script>
window.addEventListener("message", getMessage, false);
function getMessage(e) {
var content = '';
// e.data 接受傳遞訊息
content += "Get Message =>" + e.data + '<br>';
// e.origin 接受訊息domain
content += "Url from " + e.origin;
document.getElementById("response").innerHTML = "<p>" + content + "</p>";
};
</script>
...
</html>
iframe demo page
這個會比較特別,window open 是原本頁面傳給開啟頁面,iframe 則會使用 iframe embed 內部的網站傳遞資料給外部 parent,範例情境大概是修正 iframe 的高度,
範例 : (白色區塊是使用 iframe)
- 點選 iframe 內 伸縮高度按鈕
- 點擊按鈕後,會變化 body 高度,並傳值到 parent window
- parent window 接受到值後,變化 iframe style height
Source : Iframe Demo Page
iframe.html
...
<script>
// 接受傳遞訊息 變化iframe height
window.addEventListener("message", getMessage, false);
function getMessage(e) {
if(e.data.event_id) {
document.getElementById('addIframe').style.height = e.data.data + 'px';
}
};
</script>
...
embed.html
...
<script>
document.getElementById('postWindow').addEventListener('click', function (e) {
sendMsg();
});
function sendMsg() {
var height = document.body.scrollHeight;
// 向parent window 送出訊息
window.parent.postMessage(
{
event_id: 'my_cors_message',
data: height
},
"*" // or "www.parentpage.com"
);
}
</script>
...
以上就是簡單的 demo,還有更多延伸的運用,例如做出開視窗會員註冊,送出後傳遞資料回原本頁面渲染畫面。另外當你今天不得不用 iframe 的話,postMessage 會非常好用,賦予 iframe 更有彈性。另外提醒一下,實際運用要記得判斷 post Message 的網址,避免外部可能的攻擊。