欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS解決iframe之間通信和自適應(yīng)高度的問題

 更新時間:2016年08月24日 17:13:44   投稿:daisy  
關(guān)于iframe之間的通信問題與自適應(yīng)高度問題網(wǎng)上有很多,那么這篇文章小編也和大家一起來談?wù)刬frame之間通信問題及iframe自適應(yīng)高度問題,有需要的可以參考借鑒。

首先說明下,iframe通信 分為:同域通信 和 跨域通信。

一、 同域通信

所謂同域通信是指 http://localhost/demo/iframe/iframeA.html 下的a.html頁面嵌套 iframe

比如: <iframe src="http://localhost/demo/iframe/iframeB.html" id="iframeA" name="iframeA">的B.html頁面,這兩個頁面數(shù)據(jù)進(jìn)行通信,比如我想在父頁面A.html 調(diào)用子頁面當(dāng)中的函數(shù) 我們很容易想到或者google下 document.getElementById('iframeA').contentWindow.b(); 這種方法,其中b 是子頁面B.html中的一個函數(shù)。但是這樣調(diào)用下有個問題我糾結(jié)了很久,就是既然在火狐下報這樣的錯誤, 如下:

b不是個函數(shù) 但是我在子頁面明明定義了這么一個函數(shù),那么為什么會報這樣的錯誤呢?經(jīng)過仔細(xì)分析及google,發(fā)現(xiàn)有這么一個問題需要理解,當(dāng)iframe沒有加載完成后 我就去執(zhí)行這個js會報這樣的錯誤,所以就試著在火狐下 用iframe.onload 這個函數(shù) 進(jìn)行測試,果然沒有報錯,是正確的 所以就確定是這個問題。所以就想寫個兼容IE和火狐 google寫個函數(shù) 來確定iframe已經(jīng)加載完成!,其實給個回調(diào)函數(shù)來調(diào)用我們上面的方法。

綜合上面的思路 就可以寫個這樣的代碼:

<iframe src="http://localhost/demo/iframe/iframeB.html" id="iframeA" name="iframeA"></iframe>
 <div id="topName">topNddddddddddddddddame</div>
 <script>
  function A(){
  alert("A");
 }
 var iframe = document.getElementById('iframeA');
 
 iframeIsLoad(iframe,function(){
  var obj = document.getElementById('iframeA').contentWindow;
  obj.b();
 });
 
  
 
 
 function iframeIsLoad(iframe,callback){
 if(iframe.attachEvent) {
  
  iframe.attachEvent('onload',function(){
  callback && callback();
  });
 }else {
  iframe.onload = function(){
  callback && callback();
  }
 }
 }

 </script>

B.html 代碼如下:

var b = function(){
  alert("B");
 }

子頁面調(diào)用父頁面的函數(shù)很簡單,只要這樣搞下就ok了,window.parent.A();

子頁面取父頁面元素的值: window.parent.document.getElementById("topName").innerHTML等方法。

二: iframe跨域通信。

 iframe跨域訪問一般分為2種情況,第一種是同主域,不同子域的跨域。 第二種是:不同主域跨域。

1、 是同主域下面,不同子域之間的跨域;可以通過document.domain 來設(shè)置相同的主域來解決。

假如現(xiàn)在我有個域 abc.example.com 下有個頁面叫abc.html, 頁面上嵌套了一個iframe 如下:<iframe src="http://def.example.com/demo/def.html"  id="iframe2" style="display:none;"></iframe>,我想在abc域下的頁面abc.html 訪問 def域下的def.html  我們都知道由于安全性 游覽器的同源策略的限制,js不能操作頁面不同域下 不同協(xié)議下 不同端口的頁面,所以就要解決跨域訪問了,假如父頁面abc.html 頁面有個js函數(shù):function test(){console.log(1);}; 我想在子頁面調(diào)用這個函數(shù) 還是按照上面的同域方式調(diào)用 parent.test();這樣,通過在火狐下看 已經(jīng)跨域了 解決的辦法是 在各個js函數(shù)頂部 加一句 document.domain = 'example.com',就可以解決了。

abc.html代碼如下:

<iframe src="http://def.example.com/demo/def.html" id="iframe2" style="display:none;"></iframe>

// 跨域 子頁調(diào)用父頁的 函數(shù) (假設(shè)是下面test函數(shù))
document.domain = 'example.com';
function test(){console.log(1);};

def.html代碼如下:

/*
 * 子頁調(diào)用父頁的方法
 */
document.domain = 'example.com';
//window.top.test();
window.parent.test();

還是這兩個頁面 我想父頁調(diào)用子頁 如下方法:

a.html代碼如下:

/*
 * 跨域 父頁想調(diào)用子頁的的函數(shù)
 */
document.domain = 'example.com';
var iframe = document.getElementById('iframe2');
iframeIsLoad(iframe,function(){
 var obj = iframe.contentWindow;
  obj.child();
});
function iframeIsLoad(iframe,callback){
 if(iframe.attachEvent) {
  iframe.attachEvent('onload',function(){
  callback && callback();
  });
 }else {
  iframe.onload = function(){
  callback && callback();
  }
 }
 }

假如現(xiàn)在def.html頁面有個child函數(shù) 代碼如下:

document.domain = 'example.com';
function child(){console.log('我是子頁');}

就可以跨域調(diào)用了 不管是子頁面調(diào)用父頁面 還是父頁面調(diào)用子頁面。一切ok!

2、 是不同主域跨域;

 雖然google有幾種方法關(guān)于不同主域上的跨域問題 有通過location.hash方法或者window.name方法或者h(yuǎn)tml5及flash等等,但是我覺得下面iframe這種方法值得學(xué)習(xí)下,

如下圖所示:域a.com的頁面request.html(即http://a.com/demo/ajax/ajaxproxy/request.html)里面嵌套了一個iframe指向域b.com(http://b.com/demo/ajax/ajaxproxy/response.html)的response.html,而response.html里又嵌套了域a.com的proxy.html。

思路:要實現(xiàn)a.com域下的request.html頁面請求域b.com下的process.php,可以將請求參數(shù)通過url傳給response.html,由response.html向process.php發(fā)起真正的ajax請求(response.html與process.php都屬于域b.com),然后將返回的結(jié)果通過url傳給proxy.html,最后由于proxy.html和request.html是在同個域下,所以可以在proxy.html利用window.top 將結(jié)果返回在request.html完成真正的跨域。

ok, 先看看頁面結(jié)構(gòu)

a.com域下有:

     request.html

     proxy.html

b.com域下有:

    response.html

    process.php

先來看看request.html頁面如下:

<!DOCTYPE HTML>
<html>
 <head>
 <title> New Document </title>
 </head>
 
 <body>
 <p id="result">這里將會填上響應(yīng)的結(jié)果</p>
 <a id="sendBtn" href="javascript:void(0)">點擊,發(fā)送跨域請求</a>
 <iframe id="serverIf" style="display:none"></iframe>
 
 <script>
 document.getElementById('sendBtn').onclick = function() {
  var url = 'http://b.com/demo/ajax/ajaxproxy/reponse.html',
  fn = 'GetPerson',  //這是定義在response.html的方法
  reqdata = '{"id" : 24}', //這是請求的參數(shù)
  callback = "CallBack"; //這是請求全過程完成后執(zhí)行的回調(diào)函數(shù),執(zhí)行最后的動作
 
  CrossRequest(url, fn, reqdata, callback); //發(fā)送請求
 }
 
 function CrossRequest(url,fn,reqdata,callback) {
  var server = document.getElementById('serverIf');
  server.src = url + '?fn=' +encodeURIComponent(fn) + "&data=" +encodeURIComponent(reqdata) + "&callback="+encodeURIComponent(callback);
 }
 //回調(diào)函數(shù)
 function CallBack(data) {
  var str = "My name is " + data.name + ". I am a " + data.sex + ". I am " + data.age + " years old.";
  document.getElementById("result").innerHTML = str;
 }
 </script>
 </body>
</html>

  這個頁面其實就是要告訴response.html:我要讓你執(zhí)行你定義好的方法GetPerson,并且要用我給你的參數(shù)'{"id" : 24}'。response.html純粹是負(fù)責(zé)將CallBack這個方法名傳遞給下一位仁兄proxy.html,而proxy.html拿到了CallBack這個方法名就可以執(zhí)行了,因為proxy.html和request.html是同域的。

response.html代碼如下:     

<!DOCTYPE HTML>
<html>
 <head>
 <title> New Document </title>
 </head>
 
 <body>
 <iframe id="proxy"></iframe>
 <script>
 // 通用方法 ajax請求
 function _request (reqdata,url,callback) {
  var xmlhttp;
  if(window.XMLHttpRequest) {
  xmlhttp = new XMLHttpRequest();
  }else {
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  }
 
  xmlhttp.onreadystatechange = function(){
  if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
   var data = xmlhttp.responseText;
   callback(data);
  }
  }
  xmlhttp.open('POST',url);
  xmlhttp.setRequestHeader("Content-Type", "application/json; charset=utf-8");
  xmlhttp.send(reqdata);
 }
 
 // 通用方法 獲取url參數(shù)
 function _getQuery(key) {
  var query = location.href.split('?')[1],
  value = decodeURIComponent(query.split(key + "=")[1].split("&")[0]);
  return value;
 }
 
 //向process.php發(fā)送ajax請求
 function GetPerson(reqdata,callback) {
  var url = 'http://b.com/demo/ajax/ajaxproxy/process.php';
  var fn = function(data) {
  var proxy = document.getElementById('proxy');
  proxy.src = "http://a.com/demo/ajax/ajaxproxy/Proxy.html?data=" + encodeURIComponent(data) + "&callback=" + encodeURIComponent(callback);
  };
  _request(reqdata, url, fn);
 }
 
 (function(){
  var fn = _getQuery('fn'),
  reqdata = _getQuery("data"),
  callback = _getQuery("callback");
  eval(fn + "('" + reqdata +"', '" + callback + "')");
 })();
 </script>
 </body>
</html>

      這里其實就是接收來自request.html的請求得到請求參數(shù)和方法后向服務(wù)器process.php發(fā)出真正的ajax請求,然后將從服務(wù)器返回的數(shù)據(jù)以及從request.html傳過來的回調(diào)函數(shù)名傳遞給proxy.html?!?/p>

接下來看看php代碼如下,其實就是想返回一個json數(shù)據(jù):

<?php 
 $data = json_decode(file_get_contents("php://input"));
 header("Content-Type: application/json; charset=utf-8");
 echo ('{"id" : ' . $data->id . ', "age" : 24, "sex" : "boy", "name" : "huangxueming"}');
?>

最后就是proxy.html代碼:

<!DOCTYPE HTML>
<html>
 <head>
 <title> New Document </title>
 </head>
 
 <body>
 <script>
  function _getUrl(key) {//通用方法,獲取URL參數(shù)
   var query = location.href.split("?")[1],
  value = decodeURIComponent(query.split(key + "=")[1].split("&")[0]);
   return value;
  }
  (function() {
  var callback = _getUrl("callback"),
   data = _getUrl("data");
  eval("window.top." + decodeURIComponent(callback) + "(" + decodeURIComponent(data) + ")");
  })();
 </script>
 </body>
</html>

  這里也是最后一步了,proxy終于拿到了request.html透過response.html傳過來的回調(diào)函數(shù)名以及從response.html直接傳過來的響應(yīng)數(shù)據(jù),利用window.top執(zhí)行request.html里定義的回調(diào)函數(shù)。

三、iframe高度自適應(yīng)的問題。

    iframe高度自適應(yīng)分為2種,一種是同域下自適應(yīng)  另外一種是跨域下自適應(yīng),下面我們來看看同域下iframe高度自適應(yīng)的問題。

   1.同域下iframe高度自適應(yīng)的問題:

        思路:獲取被嵌套iframe元素,通過JavaScript取得被嵌套頁面最終高度,然后在主頁面進(jìn)行設(shè)置來實現(xiàn)。

假如我們demo有iframe1.html和iframe2.html

下面貼上iframe1.html代碼如下:

<!DOCTYPE HTML>
<html>
 <head>
 <title> New Document </title>
 <style>
 *{margin:0;padding:0;}
 </style>
 </head>
 
 <body>
 <iframe src="http://a.com/demo/ajax/iframeheight/iframe2.html" style="width:100%;border:1px solid #333;" frameborder="0" id="iframe"></iframe>
 
 <script>
 window.onload = function() {
  var iframeid = document.getElementById('iframe');
  if(iframeid && !window.opera) {
  if(iframeid.contentDocument && iframeid.contentDocument.body.offsetHeight) {
   iframeid.height = iframeid.contentDocument.body.offsetHeight;
  }else if(iframeid.Document && iframeid.Document.body.scrollHeight){ 
   iframeid.height = iframeid.Document.body.scrollHeight;
  }
  }
 }
 </script>
 </body>
</html>

iframe2.html

<!DOCTYPE HTML>
<html>
 <head>
 <title> New Document </title>
 <style>
 *{margin:0;padding:0;}
 </style>
 </head>
 
 <body>
 <div style="height:500px;"></div>
 </body>
</html>

就可以動態(tài)設(shè)置iframe1頁面的高度為iframe2的高度了。

 2. 跨域下iframe高度自適應(yīng)的問題。

    首先我們知道iframe跨域我們是不能用上面js方式來控制了,所以我們只能用個中間鍵 我們可以在a.com域下iframe1.html頁面嵌套一個b.com域下的iframe2.html頁面,然后我在iframe2.html頁面嵌套個和iframe1.html相同域的iframe3.html頁面了,這樣的話 iframe1.html和iframe3.html就可以無障礙的進(jìn)行通信了,因為頁面iframe2.html嵌套iframe3.html,所以iframe2.html可以改寫iframe3.html的href值。

   iframe1中的內(nèi)容:

      iframe1.html內(nèi)容主要接受iframe3.html頁面?zhèn)鬟^來的內(nèi)容并且去完成相應(yīng)的操作。iframe1.html代碼如下:

<iframe src="http://b.com/demo/ajax/iframeheight/iframe2.html" style="width:400px;height:200px;" id="iframe"></iframe> 

<script>
 var ifr_el = document.getElementById("iframe");
 function getIfrData(data){
 ifr_el.style.height = data+"px";
 }
</script>

iframe2.html中的內(nèi)容:

       iframe2.html內(nèi)容是怎么把值傳給iframe3.html頁面,剛才說了是將值傳遞到iframe3.html頁面的href中,所以只要修改iframe的src就可以,因為不用刷新C頁面,所以可以用過hash的方式傳遞給iframe3.html頁面.iframe2.html代碼如下:

<!DOCTYPE HTML>
<html>
 <head>
 <title> New Document </title>
 <style>
 *{margin:0;padding:0;}
 </style>
 </head>
 
 <body>
 <iframe id="iframe" src="http://a.com/demo/ajax/iframeheight/iframe3.html" width="0" height="230px"></iframe>
 
 <script>
 var oldHeight = 0,
  ifr_el = document.getElementById("iframe");
  
 t && clearInterval(t);
 var t = setInterval(function(){
  var height = document.body.scrollHeight;
  if(oldHeight != height) {
  oldHeight = height;
  ifr_el.src += '#' +oldHeight; 
  }
 },200);
 </script>
 </body>
</html>

         可以看到 默認(rèn)情況下 iframe1.html 頁面我給iframe2.html的高度是200像素 但是在iframe2.html我給iframe3.html高度是230像素,那么正常情況下是有滾動條的,那么現(xiàn)在我是想在iframe2.html獲取滾動條的高度,把高度傳給通過iframe3.html的src里面去,然后在iframe3.html頁面里獲取這個高度值 傳給iframe1.html(因為iframe1.html和iframe3.html是同域的),所以iframe1.html能取到這個高度值,再設(shè)置下本身的高度就是這個值就ok了。

       iframe3.html頁面的唯一功能就是接收iframe2.html頁面通過href傳進(jìn)來的值并且傳遞給iframe1.html頁面,可到iframe2.html頁面?zhèn)鱽淼闹悼梢酝ㄟ^一個定時器不停去查看location.href是 否被改變,但是這樣感覺效率很低,還有個方式就是在新的瀏覽器中通過onhashchange事件 (IE8+,Chrome5.0+,Firefox3.6+,Safari5.0+,Opera10.6+)來監(jiān)聽href的改變。

iframe3.html代碼如下:

<script>
 var oldHeight = 0;
 
 t && clearInterval(t);
 var t = setInterval(function(){
 var height = location.href.split('#')[1];
 if(height && height != oldHeight) {
  oldHeight = height;
  if(window.parent.parent.getIfrData) {
  window.parent.parent.getIfrData(oldHeight);
  }
 }
 },200);
 </script>

這樣就可以解決通過跨域?qū)崿F(xiàn)iframe自適應(yīng)高度的問題了。

四、總結(jié)

以上就是本文的全部內(nèi)容了,希望對大家的學(xué)習(xí)工作能有所幫助。如果有疑問可以留言討論。

相關(guān)文章

  • 基于原生js運動方式關(guān)鍵點的總結(jié)(推薦)

    基于原生js運動方式關(guān)鍵點的總結(jié)(推薦)

    下面小編就為大家?guī)硪黄谠鷍s運動方式關(guān)鍵點的總結(jié)(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • js表格分頁實現(xiàn)代碼

    js表格分頁實現(xiàn)代碼

    js表格分頁實現(xiàn)代碼,需要的朋友可以參考下。
    2009-09-09
  • 小程序從手動埋點到自動埋點的實現(xiàn)方法

    小程序從手動埋點到自動埋點的實現(xiàn)方法

    這篇文章主要介紹了小程序從手動埋點到自動埋點的實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • JS獲取屏幕,瀏覽器窗口大小,網(wǎng)頁高度寬度(實現(xiàn)代碼)

    JS獲取屏幕,瀏覽器窗口大小,網(wǎng)頁高度寬度(實現(xiàn)代碼)

    本篇文章主要介紹了JS獲取屏幕,瀏覽器窗口大小,網(wǎng)頁高度寬度的實現(xiàn)代碼。需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12
  • egg.js的基本使用和調(diào)用數(shù)據(jù)庫的方法示例

    egg.js的基本使用和調(diào)用數(shù)據(jù)庫的方法示例

    這篇文章主要介紹了egg.js的基本使用和調(diào)用數(shù)據(jù)庫的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 從JavaScript的函數(shù)重名看其初始化方式

    從JavaScript的函數(shù)重名看其初始化方式

    從JavaScript的函數(shù)重名看其初始化方式...
    2007-03-03
  • Javascript模仿淘寶信用評價實例(附源碼)

    Javascript模仿淘寶信用評價實例(附源碼)

    這篇文章主要介紹了Javascript模仿淘寶信用評價功能實現(xiàn)方法,以完整實例形式分析了JavaScript響應(yīng)鼠標(biāo)事件動態(tài)改變頁面元素的相關(guān)技巧,并附帶了完整的實例代碼供讀者下載參考,需要的朋友可以參考下
    2015-11-11
  • uniapp項目使用防抖及節(jié)流的方案實戰(zhàn)

    uniapp項目使用防抖及節(jié)流的方案實戰(zhàn)

    防抖就是指觸發(fā)事件后把觸發(fā)非常頻繁的事件合并成一次去執(zhí)行,節(jié)流是指頻繁觸發(fā)事件時只會在指定的時間段內(nèi)執(zhí)行事件回調(diào),即觸發(fā)事件間隔大于等于指定的時間才會執(zhí)行回調(diào)函數(shù),這篇文章主要給大家介紹了關(guān)于uniapp項目使用防抖及節(jié)流的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • 微信小程序首頁的分類功能和搜索功能的實現(xiàn)思路及代碼詳解

    微信小程序首頁的分類功能和搜索功能的實現(xiàn)思路及代碼詳解

    這篇文章主要介紹了微信小程序首頁的分類功能和搜索功能的實現(xiàn)思路及代碼詳解,微信宣布了微信小程序開發(fā)者工具新增“云開發(fā)”功能,現(xiàn)在無需服務(wù)器即可實現(xiàn)小程序的快速迭代,感興趣的朋友跟隨小編一起看看吧
    2018-09-09
  • Javascript ParentNode和ChildNode接口原理解析

    Javascript ParentNode和ChildNode接口原理解析

    這篇文章主要介紹了Javascript ParentNode和ChildNode接口原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03

最新評論