Primeiro de tudo, a comunicação Iframe é dividida em: comunicação do mesmo domínio e comunicação entre domínios.
1. Comunicação no mesmo domínio
A chamada comunicação do mesmo domínio refere-se ao iFrame aninhado da página A.HTML sob http: //localhost/demo/iframe/iframea.html
Por exemplo: <iframe src = "http: //localhost/demo/iframe/iframeb.html" id = "iframea" name = "iframea"> Os dados dessas duas páginas se comunicam. Por exemplo, quero chamar a função na página infantil na página pai A.HTML, que é fácil para nós pensarmos em document.getElementById('iframeA').contentWindow.b(); Sob o Google, onde B é uma função na página infantil B.HTML. Mas há um problema com essa chamada com a qual tenho luto há muito tempo, ou seja, desde que relatei esse erro sob o Firefox, como segue:
B não é uma função, mas eu defini claramente essa função na subpagem, então por que esse erro ocorre? Após análise cuidadosa e Google, descobri que há um problema que precisa ser entendido. Quando o iframe não tiver sido carregado, executarei este JS e relatarei esse erro. Por isso, tentei usar a função iframe.onload no Firefox para testá -lo. Com certeza, não houve erro, estava correto, então eu tinha certeza de que era esse problema. Então, eu quero escrever um IE compatível e o Firefox Google para escrever uma função para confirmar que o iframe foi carregado! , de fato, dê uma função de retorno de chamada para chamar nosso método acima.
Com base nas idéias acima, você pode escrever um código como este:
<iframe src = "http: //localhost/demo/iframe/iframeb.html" id = "iframea" name = "iframea"> </frame> <div id = "topname"> topnddddddddddddddddddddddddddddddddddddddddddd </div> <cript> function a () {alert ("a"); } var iframe = document.getElementById ('iframea'); ifRameisLoad (iframe, function () {var obj = document.getElementById ('iframea'). ContentWindow; obj.b ();}); function ifRameisLoad (iframe, retorno de chamada) {if (iframe.attachevent) {iframe.attachevent ('onLload', function () {chamada && den -retorno ();}); } else {iframe.onload = function () {retorno de chamada && retorno de chamada (); }}}} </script>O código B.HTML é o seguinte:
var b = function () {alert ("b"); } É muito simples chamar a função da página pai na página infantil. Basta fazer isso e tudo bem, window.parent.A();
A página infantil leva o valor do elemento da página pai: window.parent.document.getElementById("topName").innerHTML e outros métodos.
Dois: Comunicação de domínio cruzado do IFRAM.
O acesso ao domínio cruzado do iframe geralmente é dividido em duas situações. O primeiro é o domínio cruzado com o mesmo domínio principal e subdomínios diferentes. O segundo tipo é: diferentes domínios principais domínios cruzados.
1. É um domínio cruzado entre diferentes subdomínios no mesmo domínio principal; Ele pode ser resolvido definindo o mesmo domínio principal através do documento.Domain.
Se eu tiver um domínio abc.example.com, há uma página chamada abc.html, e um iframe é aninhado na página da seguinte forma: <iframe src = "http://def.example.com/demo/def.html" idrame2 "style =" Display: nenhum; " página abc.html Todos sabemos que, devido às limitações da política da mesma origem do navegador de segurança, o JS não pode operar páginas com diferentes portas sob diferentes protocolos sob diferentes domínios, portanto o acesso ao domínio cruzado é resolvido. Se a página pai abc.html tiver uma função js: function test(){console.log(1);}; Quero chamar essa função na subpagem ou chamar parent.test(); Dessa forma, olhando para o domínio cruzado sob o Firefox, a solução é adicionar um document.domain = 'example.com' na parte superior de cada função JS e pode ser resolvida.
O código ABC.HTML é o seguinte:
<iframe src = "http://def.example.com/demo/def.html" id = "ifRame2" style = "display: None;"> </frame> // a função que chama a página pai em relação ao domínio (função assumindo a função de consumo ).g.d);
O código def.html é o seguinte:
/** O método da página criança chamando a página pai*/document.domain = 'exemplo.com'; // window.top.test (); window.parent.test ();
Ou essas duas páginas, quero que a página pai ligue para a página criança da seguinte forma:
A.html Código é o seguinte:
/** Funções que desejam ligar para as páginas infantis na página pai do domínio*/document.domain = 'exemplo.com'; var iframe = document.getElementById ('ifRame2'); ifRameisload (ifame, function () {var obj = iframe.contentWindow; obj.Child,);); function {funct); if (iframe.attachevent) {iframe.attachevent ('onLload', function () {retorno de chamada && retorno ();}); } else {iframe.onload = function () {retorno de chamada && retorno de chamada (); }}}}Se houver um código de função filho na página def.html agora:
document.domain = 'exemplo.com'; function filho () {console.log ('eu sou uma página infantil');}Você pode ligar para os domínios, seja uma página infantil chamando a página pai ou uma página pai que chama a página infantil. Tudo está ok!
2. São diferentes domínios principais e domínios cruzados;
Embora o Google tenha vários métodos para problemas de domínio cruzado em diferentes domínios principais, incluindo o método de location.hash , método window.name , html5 e flash, etc., acho que vale a pena aprender o seguinte método iframe.
As shown in the figure below: The page request.html of domain a.com (i.e. http://a.com/demo/ajax/ajaxproxy/request.html) is nested with an iframe pointing to domain b.com (http://b.com/demo/ajaxproxy/response.html), and the proxy.html of O domínio A.com é aninhado com o proxy.html do domínio A.com.
IDEA: Para implementar a página Request.html na A.Com Domain Request Process.php sob o domínio B.com, você pode passar o parâmetro de solicitação para a resposta.html através do URL e iniciar uma solicitação de AJAX real do respostas.html para process.php (resposta.html e resultado. Finalmente, como proxy.html e request.html estão no mesmo domínio, você pode usar o Windows.top para retornar o resultado em request.html para concluir o domínio cruzado real.
Ok, vamos dar uma olhada na estrutura da página primeiro
Sob o domínio A.com, existem:
request.html
proxy.html
Sob o domínio B.com, existem:
Response.html
process.php
Vamos dar uma olhada na página Solicitação.html da seguinte forma:
<! Doctype html> <html> <head> <titter> novo documento </title> </ad Head> <body> <p id = "resultado"> O resultado da resposta será preenchido aqui </p> <a id = "sendbtn" href = "javascript: void (0)"> clique para enviar um cross-dOn Solicy <aa-As <aa> style = "Display: None"> </frame> <cript> document.getElementById ('SendBtn'). OnClick = function () {var url = 'http://b.com/demo/ajax/ajaxproxy/reponse.html' fn = 'getPerson' ,/ // isto é thishtm.html ', fn =' getPerson ',///thent.ThenTs) : 24} ', // este é o parâmetro de chamada de parâmetro solicitado = "retorno de chamada"; // Esta é a função de retorno de chamada executada após a conclusão de todo o processo de solicitação, executando a última ação CrossRequest (URL, FN, Reqdata, retorno de chamada); // Envie uma solicitação} função crossRequest (url, fn, reqdata, retorno de chamada) {var server = document.getElementById ('serverif'); server.src = url + '? fn =' + Encodeuricomponent (fn) + "& data =" + Encodeuricomponent (reqdata) + "& callback =" + Encodeuricomponent (retorno de chamada); } // Função de retorno de chamada Função de chamada (data) {var str = "Meu nome é" + data.name + ". Eu sou um" + data.sex + ". Eu sou" + data.age + "anos"; Document.getElementById ("Result"). Innerhtml = str; } </script> </body> </html> Esta página é na verdade sobre a resposta .html: quero que você execute o método que você definiu GetPerson e use o parâmetro '{"id": 24}' eu dei a você. Response.html é puramente responsável por passar o nome CallBack do método para o próximo irmão proxy.html. proxy.html pode executá -lo após obter o CallBack do nome do método, porque proxy.html e request.html estão no mesmo domínio.
O código de resposta.html é o seguinte:
<! Doctype html> <html> <head> <title> Novo documento </title> </head> <body> <iframe id = "proxy"> </frame> <cript> // Método geral AJAX Função _Request (reqdata, url, retorno) {var xmhttp; 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.ResponseTxt; retorno de chamada (dados); }} xmlhttp.open ('post', url); xmlhttp.setRequestHeader ("conteúdo-tipo", "Application/json; charset = utf-8"); xmlhttp.send (reqdata); } // Método geral para obter os parâmetros da URL função _getQuery (key) {var query = location.href.split ('?') [1], value = decodeuricomponent (query.split (key + "=") [1] .split ("&") [0]); valor de retorno; } // Envie a solicitação AJAX para process.php function getPerson (reqdata, retorno de chamada) {var url = 'http://b.com/demo/ajax/ajaxproxy/process.php'; var fn = function (dados) {var proxy = document.getElementById ('proxy'); proxy.src = "http://a.com/demo/ajax/ajaxproxy/proxy.html?data=" + Encodeuricomponent (dados) + "& chamado de retorno =" + codeuricomponent (retorno de chamada); }; _Request (reqdata, url, fn); } (function () {var fn = _getQuery ('fn'), reqdata = _getQuery ("dados"), retorno de chamada = _getQuery ("retorno de chamada"); avaliar (fn + "('" " + reqdata +"', '" + chamada +"') ");); </script> </body> </html>Na verdade, isso é para receber a solicitação do request.html e obter os parâmetros e métodos de solicitação e emitir uma solicitação AJAX real para o servidor process.php e depois passar os dados retornados do servidor e o nome da função de retorno de chamada passou do request.html para proxy.html.
Em seguida, vamos dar uma olhada no código PHP da seguinte maneira , que é realmente apenas para retornar um JSON Data:
<? php $ data = json_decode (file_get_contents ("php: // input")); Cabeçalho ("Tipo de Conteúdo: Application/Json; Charset = UTF-8"); echo ('{"id":'. $ data-> id.Finalmente, existe o código proxy.html:
<! Doctype html> <html> <head> <title> novo documento </title> </ad Head> <body> <cript> function _geturl (key) {// Método Geral, obtenha parâmetros de URL var wery = location.href.split ("? "=") [1] .split ("&") [0]); valor de retorno; } (function () {var den -retorno = _geturl ("retorno de chamada"), data = _geturl ("data"); avaliar ("window.top." + decodeuricomponent (retorno de chamada) + "(" + decodeuricomponent (dados) + "));}); </script> </body> </html>Este também é o último passo. O Proxy finalmente obteve o nome da função de retorno de chamada transmitido do request.html através do resposta.html e os dados de resposta transmitidos diretamente do Respons.html, e usou o Window.top para executar a função de retorno de chamada definida em request.html.
3. O problema da alta adaptabilidade dos iframes.
A adaptação da altura do iframe é dividida em dois tipos: um é adaptação no mesmo domínio e o outro é a adaptação sob o domínio cruzado . Vamos dar uma olhada no problema da alta adaptação no mesmo domínio.
1. Problemas com iframes altamente adaptáveis no mesmo domínio:
Ideia: Obtenha o elemento Iframe aninhado, obtenha a altura final da página aninhada através do JavaScript e, em seguida, defina -o na página principal para alcançá -la.
Se nossa demonstração tiver iframe1.html e iframe2.html
O seguinte é o seguinte código:
<! Doctype html> <html> <head> <title> novo documento </title> <style> *{margin: 0; preenchimento: 0;} </style> </weef> <body> <iframe src = "http://a.com/demo/ajax/iframhex/iframe id = "iframe"> </frame> <cript> window.onload = function () {var ifRameId = document.getElementById ('iframe'); if (ifRameId &&! window.opera) {if (ifRameId.ContentDocument && iframeid.contentDocument.body.offsetHeight) {ifRameid.Height = ifRameId.contentDocument.body.body.OffSethEight; } else if (iframeid.document && iframidid.document.body.scrolHeight) {ifRameid.Height = ifRameid.document.body.scrolHeight; }}} </script> </body> </html>iframe2.html
<! Doctype html> <html> <head> <title> novo documento </title> <yoy> *{margem: 0; preenchimento: 0;} </style> </head> <body> <div style = "altura: 500px;"> </div> </body> </html>Você pode definir dinamicamente a altura da página IFRAME1 como IFRAME2 Hight.
2. Os iframes são altamente adaptáveis entre os domínios.
Primeiro de tudo, sabemos que não podemos controlar os domínios cruzados dos iframes com o método JS acima, para que possamos usar apenas a chave intermediária para aninhar uma página iframe2.html sob o domínio B.com na página iframe1.html no domínio A.com, e então eu nadem um ifht3. Dessa forma, o iframe1.html e iframe3.html podem se comunicar sem barreiras, porque a página iframe2.html ninhos iframe3.html, portanto, iframe2.html pode reescrever o valor HREF do ifRame3.html.
Conteúdo no iframe1:
O conteúdo iframe1.html aceita principalmente o conteúdo transmitido da página iframe3.html e conclui a operação correspondente. O código iframe1.html é o seguinte:
) função getifrdata (dados) {ifr_el.style.Height = Data+"px"; } </script>Conteúdo em iframe2.html:
Como o conteúdo iframe2.html passa o valor para a página iframe3.html? Acabei de dizer que o valor é passado para o href da página iframe3.html, então basta modificar o SRC do iframe. Como não há necessidade de atualizar a página C, ela pode ser passada para a página iframe3.html por hash. O código de iframe2.html é o seguinte:
<! Doctype html> <html> <head> <title> novo documento </title> <style> *{margin: 0; preenchimento: 0;} </style> </ad head> <body> <iframe id = "ifRame" src = "http:/a.com/demo/ajAxx/frame" var OldHeight = 0, ifr_el = document.getElementById ("iframe"); t && clearInterval (t); var t = setInterval (function () {var altura = document.body.ScrolHeight; if (OldHeight! = altura) {OldHeight = altura; ifr_el.src += '#' +OldHeight;}}, 200); </script> </body> </html>Você pode ver que, por padrão, a altura da página iframe1.html que eu dou iframe2.html é de 200 pixels, mas no iframe2.html eu dou iframe3.html a altura da altura do iframe3.html é de 230 pixels; portanto, em circunstâncias normais, existe uma barra de rolagem. Now I want to get the height of the scroll bar in iframe2.html, pass the height to the src through iframe3.html, and then get the height value in the iframe3.html page to pass it to iframe1.html (because iframe1.html and iframe3.html are in the same domain), so iframe1.html can get this height value, and then set the Altura em si, está tudo bem.
A única função da página iframe3.html é receber o valor passado pela página iframe2.html através do href e passá -lo para a página iframe1.html. O valor passado para a página iframe2.html pode ser verificado continuamente através de um cronômetro para ver se o local.HREF foi alterado, mas isso é muito ineficiente. Outra maneira é ouvir as mudanças do HREF através onhashchange (IE8+, Chrome5.0+, Firefox3.6+, Safari5.0+, Opera10.6+) no novo navegador.
O código iframe3.html é o seguinte:
<Cript> var OldHeight = 0; t && clearInterval (t); var t = setInterval (function () {var de altura = localização.href.split ('#') [1]; if (altura && altura! = OldHeight) {OldHeight = height; if (window.parent.parent.getifrdata) {window.parent.parent.getifrdata (antigo); </script>Isso pode resolver o problema de alcançar a altura da adaptabilidade do iFrame através do domínio cruzado.
4. Resumo
O acima é o conteúdo inteiro deste artigo. Espero que seja útil para estudar e trabalhar de todos. Se você tiver alguma dúvida, deixe uma mensagem para discutir.