Tout d'abord, la communication IFRAME est divisée en: communication du même domaine et communication inter-domaine.
1. Communication dans le même domaine
La communication dite du grand domaine fait référence à la page Iframe imbriquée de A.Html sous http: //localhost/demo/iframe/iframea.html
Par exemple: <iframe src = "http: //localhost/demo/iframe/iframeb.html" id = "iframea" name = "iframea"> Les données de ces deux pages communiquent. Par exemple, je souhaite appeler la fonction dans la page enfant de la page parent A.Html, ce qui est facile pour nous de penser à document.getElementById('iframeA').contentWindow.b(); Sous Google, où B est une fonction dans la page de l'enfant B.HTML. Mais il y a un problème avec cet appel avec lequel je lutte depuis longtemps, c'est-à-dire que j'ai signalé une telle erreur sous Firefox, comme suit:
b n'est pas une fonction, mais j'ai clairement défini une telle fonction sur la sous-page, alors pourquoi une telle erreur se produit-elle? Après une analyse minutieuse et Google, j'ai constaté qu'il y avait un problème qui doit être compris. Lorsque l'IFRAME n'a pas été chargé, je vais exécuter ce JS et signaler une telle erreur. J'ai donc essayé d'utiliser la fonction iframe.onload sous Firefox pour la tester. Effectivement, il n'y avait pas d'erreur, c'était correct, donc j'étais sûr que c'était ce problème. Je veux donc écrire un IE compatible IE et Firefox Google pour écrire une fonction pour confirmer que l'IFRAME a été chargé! , en fait, donnez une fonction de rappel pour appeler notre méthode ci-dessus.
Sur la base des idées ci-dessus, vous pouvez écrire un code comme celui-ci:
<iframe src = "http: //localhost/demo/iframe/iframeb.html" id = "iframea" name = "iframea"> </ iframe> <div id = "topname"> topndddddddddddddddddddddddddddddddddddddddd </div> <script> function a () {alert ("a"); } var iframe = document.getElementById ('iframea'); iframeisload (iframe, function () {var obj = document.getElementById ('iframea'). ContentWindow; obj.b ();}); fonction iframeisload (iframe, callback) {if (iframe.attachevent) {iframe.attachevent ('onload', function () {callback && callback ();}); } else {iframe.onload = function () {callback && callback (); }}}} </ script>Le code B.HTML est le suivant:
var b = function () {alert ("b"); } Il est très simple d'appeler la fonction de la page parent sur la page enfant. Faites-le et ce sera OK, window.parent.A();
La page de l'enfant prend la valeur de l'élément de page parent: window.parent.document.getElementById("topName").innerHTML et autres méthodes.
Deux: Communication inter-domaine iframe.
L'accès au domaine croisé IFRAME est généralement divisé en deux situations. Le premier est le domaine croisé avec le même domaine principal et différents sous-domaines. Le deuxième type est: différents domaines principaux.
1. Il s'agit d'un domaine croisé entre différents sous-domaines sous le même domaine principal; Il peut être résolu en définissant le même domaine principal via Document.Domain.
Si j'ai un domaine abc.example.com, il y a une page appelée ABC.html, et un iframe est imbriqué sur la page comme suit: <iframe src = "http://def.example.com/demo/def.html" id = "iframe2" style = "Afficher: non;"> </frame>, je veux accéder à la def. Page ABC.HTML Nous savons tous qu'en raison des limites de la politique d'origine même du navigateur de sécurité, JS ne peut pas utiliser de pages avec différents ports sous différents protocoles dans différents domaines, donc l'accès inter-domaine est résolu. Si la page parent ABC.html a une fonction JS: function test(){console.log(1);}; Je souhaite appeler cette fonction sur le sous-page ou appeler parent.test(); De cette façon, en regardant le domaine croisé sous Firefox, la solution consiste à ajouter un document.domain = 'example.com' en haut de chaque fonction JS, et elle peut être résolue.
Le code ABC.HTML est le suivant:
<iframe src = "http://def.example.com/demo/def.html" id = "iframe2" style = "affiche: aucun;"> </ iframe> // La fonction qui appelle la page parent à travers les sous-pages du domaine (en supposant est la fonction de test ci-dessous) document.domain = 'example'; fonction test () {console.Log (1);};Le code Def.html est le suivant:
/ * * La méthode de la page enfant appelant la page parent * / document.domain = 'example.com'; // window.top.test (); window.parent.test ();
Ou ces deux pages, je veux que la page parent appelle la page enfant comme suit:
Le code A.HTML est le suivant:
/ * * Fonctions qui souhaitent appeler les pages enfants à travers la page parent de domaine * / document.domain = 'example.com'; var iframe = document.getElementyid ('iframe2'); ifraTeisLoad (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 (); }}}}S'il y a un code de fonction enfant sur la page DEF.html maintenant:
document.domain = 'example.com'; fonction child () {console.log ('je suis une page enfant');}Vous pouvez appeler à travers des domaines, qu'il s'agisse d'une page d'enfant qui appelle la page parent ou une page parent appelant la page enfant. Tout va bien!
2. Ce sont des domaines principaux et des domaines transversaux différents;
Bien que Google ait plusieurs méthodes pour les problèmes de domaine transversal sur différents domaines principaux, y compris la méthode location.hash , window.name Method, HTML5 et Flash, etc., je pense que la méthode IFRAME suivante vaut la peine d'être apprise.
Comme le montre la figure ci-dessous: la page demande.html du domaine a.com (c'est-à-dire http://a.com/demo/ajax/ajaxproxy/request.html) est imbriqué avec un iframe pointer vers Domain b.com (http://b.com/demo/ajaxproxy/response.html), et le proxy. du domaine a.com est imbriqué du proxy.html du domaine a.com.
IDEA: pour implémenter la page demande.html sous le domaine A.COM Demande Process.php sous le domaine B.com, vous pouvez transmettre le paramètre de demande à la réponse.html via l'URL, et lancer une véritable demande ajax de la réponse.html pour procéder.php (réponse.html et process.php appartient au domaine), et ensuite passer le résultat retourné au proxy.html par le domaine), et ensuite passer le résultat retourné au proxy.html par le domaine), et ensuite passer le résultat retourné à Proxy.html par le domaine), et ensuite passer le résultat retourné à Proxy.html par le domaine), et ensuite passer le résultat retourné à Proxy. Enfin, puisque proxy.html et request.html sont dans le même domaine, vous pouvez utiliser Window.top pour retourner le résultat dans request.html pour compléter le vrai domaine croisé.
Ok, jetons un coup d'œil à la structure de la page en premier
Dans le domaine A.COM, il y a:
request.html
proxy.html
Dans le domaine B.Com, il y a:
réponse.html
process.php
Jetons un coup d'œil à la page de demande.html comme suit:
<! Doctype html> <html> <éad- head> <itle> nouveau document </tapt> </ad> <gody> <p id = "result"> Le résultat de la réponse sera rempli ici </p> <a id = "SendBtn" href = "javascript: void (0)"> cliquez pour envoyer une demande croisée </a> <iframe id = "serveur" style = "affiche: aucun"> </ iframe> <cript> document.getElementById ('sendbtn'). onClick = function () {var url = 'http://b.com/demo/ajax/ajaxproxy/reponse.html', fn = 'getPerson' : 24} ', // c'est le paramètre demandé callback = "callback"; // Il s'agit de la fonction de rappel exécutée une fois l'ensemble du processus de demande terminé, exécutant la dernière action CrossRequest (URL, FN, reqdata, rappel); // Envoyer une demande} fonction CrossRequest (URL, fn, reqdata, rappel) {var server = document.getElementById ('serverIF'); server.src = url + '? fn =' + EncodeuRIComponent (fn) + "& data =" + EncodeuRIComponent (reqdata) + "& callback =" + EncodeuRIComponent (callback); } // Fonction de rappel Fonction Rappel (données) {var str = "Mon nom est" + data.name + ". Je suis un" + data.sex + ". Je suis" + data.age + "ans."; document.getElementById ("Result"). InnerHtml = Str; } </ script> </ body> </html> Cette page consiste en fait à raconter une réponse.html: Je veux que vous exécutiez la méthode que vous avez définie GetPerson et utilisez le paramètre '{"id": 24}' Je vous ai donné. Response.html est purement responsable du passage du CallBack du nom de la méthode au prochain frère proxy.html. proxy.html peut l'exécuter après avoir obtenu le CallBack du nom de méthode, car proxy.html et request.html sont dans le même domaine.
Le code de réponse.html est le suivant:
<! Doctype html> <html> <éadf> <itle> nouveau document </ title> </ head> <body> <iframe id = "proxy"> </frame> <script> // méthode générale ajax request 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; rappel (données); }} xmlhttp.open ('post', URL); xmlhttp.setRequestHeader ("contenu-type", "application / json; charset = utf-8"); xmlhttp.send (reqdata); } // Méthode générale pour obtenir des paramètres URL fonction _GETQUERY (key) {var query = location.href.split ('?') [1], value = decodeuriComponent (query.split (key + "=") [1] .split ("&") [0]); valeur de retour; } // Envoi de la demande AJAX à la fonction process.php getPerson (reqdata, rappel) {var url = 'http://b.com/demo/ajax/ajaxproxy/process.php'; var fn = fonction (data) {var proxy = document.getElementyId ('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 +"') ");}) (); </cript> </ body> </html>Il s'agit en fait de recevoir la demande de request.html et d'obtenir les paramètres et méthodes de demande, puis émettez une véritable demande AJAX au serveur process.php, puis transmettez les données renvoyées du serveur et le nom de la fonction de rappel passé de demande.html à proxy.html.
Ensuite, jetons un coup d'œil au code PHP comme suit , qui est en fait juste pour retourner une données JSON:
<? php $ data = json_decode (file_get_contents ("php: // input")); en-tête ("contenu-type: application / json; charset = utf-8"); echo ('{"id":'. $ data-> id. ', "âge": 24, "sexe": "boy", "nom": "huangxueming"}');?>Enfin, il y a le code proxy.html:
<! Doctype html> <html> <éad- head> <itle> nouveau document </title> </ head> <body> <script> function _getUrl (key) {// Méthode générale, get Url Paramètres var query = location.href.split ("?") [1], value = decodeuriComponent (query.split (Key + + "=") [1] .split ("&") [0]); valeur de retour; } (function () {var callback = _getUrl ("callback"), data = _getUrl ("data"); eval ("window.top." + decodeuriComponent (callback) + "(" + decodeuriComponent (data) + ")");}) (); </cript> </ body> </html>C'est aussi la dernière étape. Proxy a finalement obtenu le nom de fonction de rappel transmis à partir de request.html via réponse.html et les données de réponse transmises directement à partir de réponse.html, et utilisé Window.top pour exécuter la fonction de rappel définie dans request.html.
3. Le problème de l'adaptabilité élevée des iframes.
L'adaptation de la hauteur du nom IFRAME est divisée en deux types: l'une est l'adaptation sous le même domaine et l'autre est l'adaptation sous le domaine croisé . Jetons un coup d'œil au problème de l'adaptation élevée dans le même domaine.
1. Problèmes avec des iframes hautement adaptables dans le même domaine:
Idée: Obtenez l'élément IFRAME imbriqué, obtenez la hauteur finale de la page imbriquée via JavaScript, puis définissez-la sur la page principale pour l'atteindre.
Si notre démo a iframe1.html et iframe2.html
Ce qui suit est le code suivant:
<! Doctype html> <html> <éad- head> <itle> nouveau document </Title> <style> * {margin: 0; padding: 0;} </pyle> </ head> <body> <iframe src = "http://a.com/demo/ajax/iframeHeight/iframe2.html" frameborder = "0" 0 "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> <éad- head> <itle> nouveau document </ title> <style> * {margin: 0; padding: 0;} </ style> </ head> <body> <div style = "height: 500px;"> </div> </ body> </html>Vous pouvez définir dynamiquement la hauteur de la page IFRAME1 sur la hauteur IFRAME2.
2. Les iframes sont très adaptables entre les domaines.
Tout d'abord, nous savons que nous ne pouvons pas contrôler le domaine croisé des iframes avec la méthode JS ci-dessus, nous ne pouvons donc utiliser la clé intermédiaire que pour nidifier une page iframe2.html sous le domaine B.com sur la page iframe1.html sous le domaine A.COM, puis je niche une page Iframe3.html avec la page de même domaine comme iframe1. De cette façon, iframe1.html et iframe3.html peuvent communiquer sans barrières, car la page iframe2.html niche iframe3.html, donc iframe2.html peut réécrire la valeur href d'Iframe3.html.
Contenu dans iframe1:
Le contenu iframe1.html accepte principalement le contenu transmis à partir de la page IFRAME3.html et termine l'opération correspondante. Le code iframe1.html est le suivant:
<iframe src = "http://b.com/demo/ajax/iframeheight/iframe2.html" id = "iframe"> </ iframe> <cript> var ifr_el = document.getElementById ("iframe"); fonction getIfrData (data) {ifr_el.style.height = data + "px"; } </ script>Contenu dans iframe2.html:
Comment le contenu iframe2.html passe-t-il la valeur à la page iframe3.html? Je viens de dire que la valeur est transmise au HREF de la page iframe3.html, alors modifiez simplement le SRC de l'Iframe. Parce qu'il n'est pas nécessaire de rafraîchir la page C, il peut être transmis à la page iframe3.html par hash. Le code d'Iframe2.html est le suivant:
<! Doctype html> <html> <éad- head> <itle> nouveau document </ title> <style> * {margin: 0; padding: 0;} </ style> </ head> <corps 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); </cript> </ body> </html>Vous pouvez voir que par défaut, la hauteur de la page iframe1.html que je donne iframe2.html est de 200 pixels, mais dans iframe2.html, je donne iframe3.html, la hauteur de l'Iframe3.html est de 230 pixels, donc dans des circonstances normales, il y a une barre de scroll. Maintenant, je veux obtenir la hauteur de la barre de défilement dans iframe2.html, transmettre la hauteur au src via iframe3.html, puis obtenir la valeur de hauteur dans la page iframe3.html pour la passer à iframe1.html (car iframe1.html et iframe3.html, puis la valeur du domaine), donc iframe1.html hauteur elle-même, c'est ok.
La seule fonction de la page iframe3.html est de recevoir la valeur transmise par la page iframe2.html via le HREF et la transmettre à la page iframe1.html. La valeur transmise à la page iframe2.html peut être vérifiée en continu via une minuterie pour voir si l'emplacement.href a été modifié, mais cela semble très inefficace. Une autre façon consiste à écouter les changements de HREF via onhashchange (IE8 +, Chrome5.0 +, Firefox3.6 +, Safari5.0 +, Opera10.6 +) dans le nouveau navigateur.
Le code iframe3.html est le suivant:
<Script> var oldheight = 0; t && clearInterval (t); var t = setInterval (function () {var height = location.href.split ('#') [1]; if (height && height! = oldheight) {oldheight. </cript>Cela peut résoudre le problème de la réalisation de la hauteur de l'adaptabilité d'Iframe par le domaine croisé.
4. Résumé
Ce qui précède est l'intégralité du contenu de cet article. J'espère que cela sera utile à l'étude et au travail de chacun. Si vous avez des questions, veuillez laisser un message à discuter.