歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~
本文主要會介紹如何基於MessengerJS,實現iframe父窗體與子窗體間的通訊,傳遞資料資訊。同時本文會提供一個可執行的例項程式碼,實現在父窗體中,獲取到來自子窗體的資料的效果。
0.背景介紹
(1)需要在當前的前端專案中,使用iframe巢狀別的站點頁面。
(2)當子窗體觸發了一個事件後,要給父窗體傳一個跳轉地址的url。父窗體監聽到這個事件後,根據接收到的url,來更新當前父窗體的url,實現頁面的跳轉。
1.採用方案
1.1 MessengerJS方案
可以採用MessengerJS方案,該方案可以實現父窗體與iframe之間的通訊、多個iframe之間的通訊。不過要前提是要確保對不同域的頁面有修改許可權,並且父窗體、子窗體頁面都要同時載入這個MessengerJS。
1.2 使用方法
(1) 在需要通訊的父窗體、和子窗體的文件中,都需要引入MessengerJS。
(2) 父窗體和子窗體各自的文件(document)中,都需要自己的Messenger與其他文件通訊,父窗體和子窗體的window物件都對應著有且僅有一個Messenger物件,該Messenger物件會負責當前window的所有通訊任務。因此,每個Messenger物件都需要唯一的名字,這樣它們之間才可以知道是在跟誰通訊。另外,MessengerJS方案推薦指定專案名稱,(類似名稱空間的作用),以增強程式碼健壯性與元件複用性,避免未來與其他專案衝突。(注意: 專案名稱應使用字串型別)
父窗體與子窗體初始化Messenger物件:
// 父視窗中 - 初始化Messenger物件
// 推薦指定專案名稱, 避免Mashup類應用中, 多個開發商之間的衝突
var messenger = new Messenger(`Parent`, `projectName`);
// iframe中 - 初始化Messenger物件
// 注意! Messenger之間必須保持專案名稱一致, 否則無法匹配通訊
var messenger = new Messenger(`iframe1`, `projectName`);
// 多個iframe, 使用不同的名字
var messenger = new Messenger(`iframe2`, `projectName`);
(3) 在發現訊息前,目標文件要確保已經監聽了訊息事件:
messenger.listen(function(msg){
alert("收到訊息: " + msg);
});
(4) 父窗體想給子窗體發資訊,要新增訊息物件,明確告知當前的父窗體,要傳送訊息的子窗體的window引用與messenger物件的名字:
// 父視窗中 - 新增訊息物件, 明確告訴父視窗iframe的window引用與名字
messenger.addTarget(iframe1.contentWindow, `iframe1`);
// 父視窗中 - 可以新增多個訊息物件
messenger.addTarget(iframe2.contentWindow, `iframe2`);
(5) 發訊息時,要指定messenger的名字和訊息,例如父窗體要給子窗體發訊息:
// 父視窗中 - 向單個iframe發訊息
messenger.targets[`iframe1`].send(msg1);
messenger.targets[`iframe2`].send(msg2);
// 父視窗中 - 向所有目標iframe廣播訊息
messenger.send(msg);
2.例項
基於上面的介紹,下面要實現開篇提出的需求了(例項程式碼只是示例如何傳遞資料,沒有更改父窗體url)。這裡分別是父窗體和子窗體的程式碼實現,可直接在瀏覽器中開啟檢視效果,其中messenger.js可以在這裡下載,放到專案目錄下。
父窗體:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>父窗體</title>
<style type="text/css"></style>
<!-- 這個messenger.js可下載放到專案目錄下 -->
<script type="text/javascript" src="./messenger.js"></script>
</head>
<body>
<div>這是父窗體</div>
<div id="msg"></div>
<iframe id="iframe1" name="iframe1" src="./child.html" width="600px" height="316px" style="z-index: 100000;position: absolute;">
</iframe>
</body>
<script type="text/javascript">
//父頁面中,註冊一個messager到一個統一的專案中,第一個引數為自己頁面的名稱,第二個引數為專案名稱
var messenger = new Messenger(`parent`, `monitor`),
iframe1 = document.getElementById(`iframe1`);
//父頁面中繫結監聽訊息事件,當接受到iframe1發來的訊息後執行
messenger.listen(function (msg) {
// alert(msg);
var oDiv = document.getElementById("msg");
oDiv.innerHTML += msg;
//todo
});
</script>
</html>
子窗體:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>子窗體</title>
<style type="text/css"></style>
<!-- 這個messenger.js可下載放到專案目錄下 -->
<script type="text/javascript" src="./messenger.js"></script>
</head>
<body>
<div style="background: #8CB08B;height:300px;">
<div>這是子窗體</div>
<input type="button" onclick="sendMessage(`這是一條來自子窗體的訊息!`)" value="按鈕" />
</div>
</body>
<script type="text/javascript">
//子頁面中,註冊一個messager到一個統一的專案中,第一個引數為自己頁面的名稱,第二個引數為專案名稱
var messenger = new Messenger(`iframe1`, `monitor`);
//新增訊息物件, 明確告訴子視窗iframe的window引用與名字
messenger.addTarget(window.parent, "parent");
function sendMessage(msg) {
messenger.targets["parent"].send(msg);
}
</script>
</html>
程式碼解釋:
父窗體中嵌入iframe,要先引入messenger.js,同時初始化messenger到一個統一的專案中,其中第一個引數為自己頁面messenger物件的名字,第二個引數為專案名稱;然後父窗體要繫結監聽訊息事件,當接收到iframe子窗體發來的訊息後執行。
子窗體也要先引入messenger.js,同時初始化一個messenger到一個統一的專案中,其中第一個引數為自己頁面messenger物件的名字,第二個引數為專案名稱;然後新增訊息物件,告知子窗體的window引用與messenger物件的名字。然後在觸發onclick事件時,向父視窗傳遞訊息。發訊息時,要指定接收訊息的父窗體的messenger的名字,以及傳遞的訊息。
3.小結
本文主要是介紹了一個MessengerJS方案及其使用方法,來解決父窗體與子窗體的通訊問題。同時提供了一個完整的例項,可以實現子窗體向父窗體傳遞訊息,父窗體通過監聽訊息事件,來獲取子窗體訊息的目的。如有問題,歡迎指正。
此文已由作者授權騰訊雲+社群釋出,更多原文請點選
搜尋關注公眾號「雲加社群」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社群!