Iframe父子視窗之間的跨域事件調用和傳值

来源:http://www.cnblogs.com/lycnblogs/archive/2017/10/18/7687255.html
-Advertisement-
Play Games

實現方案1:location.hash傳值 父頁面:parent.html(所在域:www.parent.com) 子頁面:child.html(所在域:www.child.com) 要實現父子頁面雙向的事件調用和傳值,需要多加一個代理頁面,主要用於子頁面調用父頁面的方法 代理頁面:proxy.ht ...


實現方案1:location.hash傳值

父頁面:parent.html(所在域:www.parent.com)

子頁面:child.html(所在域:www.child.com)

要實現父子頁面雙向的事件調用和傳值,需要多加一個代理頁面,主要用於子頁面調用父頁面的方法

代理頁面:proxy.html(所在域:www.parent.com)必須與父頁面在同域下

 

父頁面調用子頁面方法(即事件通過父頁面發起,在子頁面中執行):

父頁面中直接設置iframe的src中的hash值

parent.html:

var frameurl = "http://www.child.com/child.html"
document.getElementById("frameId").src=frameurl+"#action="+actionName+"&data="+dataJSONStr;

子頁面中設置定時器監聽hash的變化,監聽到後直接執行該方法

child.html:

var currentHash = location.hash;

setInterval(function(){

var hash = location.hash.substring(1);

if(currentHash!==hash){

  var action = ...;

  var data = ...;

  childFuncClass[action](data);

}

},1);

同樣可以使用onhashchange事件監聽到

子頁面調用父頁面方法(事件通過子頁面發起,在父頁面中執行)

在子頁面child.html中添加一個iframe鏈接到上面所說的proxy.html,child.html中通過改變proxy.html的hash值,在proxy.html中監聽hash變化事件,監聽到以後直接調用parent.html中的方法(與父頁面調用子頁面方法一致)

proxy.html:

var currentHash = location.hash;

setInterval(function(){

var hash = location.hash.substring(1);

if(currentHash!==hash){

  var action = ...;

  var data = ...;

  window.parent.parent[action](data);

}

},1);

  

存在問題:

data長度限制,在chrome,ff,safari等瀏覽器中hash長度限制有50K以上,但是在ie下最多2000左右的限制。

 

回調函數的處理

通常情況下父頁面在調用子頁面的方法時會有一些回調函數(函數是在parent.html中編寫和執行,但是需要child.html中的方法執行完成後再執行,有些情況下會需要child.html中執行的結果)

比如(通常情況下會做介面的封裝):

parent.html:

var data={.....};

childFunc.func1(data,function(result){

//result即為child.html中執行func1後的結果值

});

  

child.html:

var func1 = function(data,callback){

//對data的一些操作

var result = ...;

callback&&callback(result);

}

  

如果出現這種情況的話parent.html中定義的匿名回調函數是不可能以字元串的形式傳遞到child.html中去的,並且也無法在child.html中再去執行父頁面的回調函數

解決方法:

在介面封裝的時候將回調函數保存下來,通過一個唯一的函數名傳遞到child.html中,child.html中的方法執行完成後將該函數名傳遞到proxy.html中執行該函數

以上面的func1為例

parent.html:

var eventIndex=0;
childFunc.func1 = function(data,callback){
    if(//callback是function類型){
        //此時window是parent頁面的對象
        window["myEvent"+eventIndex] = callback;
childIframe.hash="action=...&data=...&callback=myEvent"+eventIndex;
} };

  

child.html:

var currentHash = location.hash;

setInterval(function(){

var hash = location.hash.substring(1);

if(currentHash!==hash){

  var action = ...;

  var data = ...;
      
   var callback=....;//應該是myEvent+index

  childFuncClass[action](data,function(result){
    proxyIfram.src.hash="action="+callback+"&data="+result;
  });

}

},1);

  

proxy.html:

setInterval(function(){

  if(//hash changed){

    var callback  = //hash.callback
    var callbackData = //hash.callbackData
    window.parent.parent[callback](callbackData);
  }

},1);

  

實現方案2:window.postMessage方法

由於方案1中對ie相容性有問題(所有ie版本,包括ie11和edge都存在這個問題),方案2使用postMessage方法,該方法理論上對數據量沒有限制(猜的),並且對ie可用

同樣是使用iframe嵌入,

parent.html

var iframe = document.getElementById("childFrame").contentWindow;
var msg = {data:parentData,action:childFunc,callback:/*類似於上面的方法myEventIndex*/}
var childDomain = "http://www.child.com"
iframe.postMessage(msg,childDomain);
window.addEventListener("message",function(obj){
    var data = obj.data;
    var action = data.action;
    var data = data.data;
    parentFuncClass[action](data);
});

  

child.html

window.addEventListener("message",function(obj){
    var data = obj.data;
    var action = data.action;
    var data = data.data;
    var callback = data.callback;
    childFuncClass[action](data,function(result){
          var d = {action:callback,data:result};
          var parentDomain="http://www.parent.com";
          window.parent.postMessage(d,parentDomain);
    });
});

  

真的是坑啊,把方案1中的坑都走過後才找到方案2的方法


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本博客參考自https://github.com/cipchk/ngx-bootstrap-modal和https://valor-software.com/ngx-bootstrap/#/modals,這兩個網址幾乎涵蓋了所有的angular彈框 ...
  • 在canvas中,要畫出1px的線條,預設情況下是不行的 上述代碼中,context是canvas的上下文,在這段代碼中,我畫了2條線,上面那條線並不是1px,下麵的那條線才是1px 上面你可能還看不清楚,那條黑線到底是不是1px,你可以把他們放到畫圖軟體或者photoshop中,放大,然後打開坐標 ...
  • 寫CSS時給容器設置透明度的時候如果使用background-color: #000000; opacity: 0.5;這時會出現容器里的文字也跟著透明。解決辦法是不用十六進位的色值和透明度分開寫,使用background-color: rgba(000, 000, 000, 0.5);這樣容器內的 ...
  • var day1 = new Date("2017-9-17"); var day2 = new Date("2017-10-18"); console.log((day2 - day1) / (1000 * 60 * 60 * 24)); ...
  • vue 集成axios之後,發送的post請求預設為payload 方式。 如果想改為正常的方式,需要增加headers頭,並且將發送是數據json格式改為 querystring的方式。 安裝依賴 導入依賴 在需要使用post的地方使用下麵的方法,其中postData是一個json對象 這樣,發送 ...
  • html: <div class="nav"> <ul> <li class="active"><a href="a.html">aaa</a></li> <li><a href="b.html">bbb</a></li> <li><a href="c.html">ccc</a></li> </ul ...
  • 雙擊節點,節點以及節點一度關聯的節點保持高亮狀態,其餘節點變灰,半徑變小,文字消失,並且向內收縮。 ...
  • function tab(date1,date2){ var oDate1 = new Date(date1); var oDate2 = new Date(date2); if(oDate1.getTime() > oDate2.getTime()){ console.log('第一個大'); }... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...