跨域庫herryPostMessage.js的一些優化,多iframe跨域
- 2021 年 4 月 15 日
- 筆記
- postMessage, 前端, 前端筆記, 跨域
舊庫見文章://www.cnblogs.com/wuhairui/p/14595893.html
新版庫主要做了下多個iframe和父頁面交互的優化。主要使用構造函數的方式將多個iframe的交互使用多個對象進行區分,這樣多個交互就可以互相獨立了。
並可子頁面主動調用傳值給父頁面。
新版代碼:
/** * iframeId iframe的id * parentName 父窗口名,一般不改 * childName 子窗口名 多個iframe時需要使用 * postMessage 父窗口調用 需要子頁面加載完成後才能執行到 * returnData 子窗口主動回應 * callback 父窗口調用後子窗口判斷 */ (function (w) { function HerryPostMessage(iframeId = 'iframe') { this.iframeId = iframeId; this.parentName = '父窗口'; this.childName = '子窗口'; //跨域對象 this.messageObj = {}; /** * 監聽父頁面發送的數據 */ w.addEventListener( "message", async (event) => { const { data } = event; if (data && typeof data === "object" && data.name === this.parentName) { if (this.callback) { this.callback(data) } } }, false ); /** * 監聽子頁面返回的數據 */ w.addEventListener( "message", (event) => { const { data } = event; if (data && typeof data === "object" && data.name === this.childName) { if(this.messageObj[data.action]) { this.messageObj[data.action](data); } } }, false ); } //父頁面 /** * 發送給子頁面數據 */ HerryPostMessage.prototype.postMessage = function(data, fn = null) { const iframe = document.getElementById(this.iframeId) iframe.contentWindow.postMessage( { name: this.parentName, //父頁面名字 ...data, }, "*" ); this.messageObj[data.action] = fn; }; //子頁面 /** * 返回數據給父頁面 參1=當前action 參2=返回的數據 */ HerryPostMessage.prototype.returnData = function(action, data) { top.postMessage( { name: this.childName, //子頁面名字 action, data, }, "*" ); }; //拋出 w.HerryPostMessage = HerryPostMessage; })(window);
使用方法:
父子頁面均引入herryPostMessage.js。
父頁面:
引入子頁面b1,設置一個id
<iframe id="b1" src="//localhost:8081/b1.html" frameborder="0"></iframe>
創建對象,參數傳參為iframe的id,設置對象的childName也同名。
父子頁面均加載後,調用對象的postMessage方法,傳入action,data可傳可不傳。第二個參數為子頁面的回調。
const b1 = new HerryPostMessage('b1') b1.childName = 'b1'; //此處需要延遲 因為到登錄子頁面加載完畢 setTimeout(() => { b1.postMessage({action:'geta',data: '父頁面傳給子頁面的數據'},(res) => { console.log('父頁面打印',res.data) }) },500)
子頁面:
創建該頁面的對象(一般和父頁面創建的同名)
創建callback函數,做判斷,父頁面調用後,會進入到這裡。處理後可以使用對象的returnData方法將數據傳回給父頁面的回調函數中。
const b1 = new HerryPostMessage('b1'); b1.childName = 'b1'; b1.callback = (data) => { if(data.action === 'geta') { //獲取到父頁面傳來的數據 console.log('子頁面打印',data.data) //子頁面回傳給父頁面數據 b1.returnData('geta','子頁面回傳給父頁面數據') } }
另外,在子頁面中直接調用returnData也可以主動傳回給父頁面數據
setTimeout(() => { b1.returnData('geta','子頁面主動傳給父頁面數據') },1000)
效果:


