ก่อนอื่นการสื่อสาร IFRAME แบ่งออกเป็น: การสื่อสารโดเมนเดียวกันและการสื่อสารข้ามโดเมน
1. การสื่อสารในโดเมนเดียวกัน
การสื่อสารที่เรียกว่าโดเมนเดียวกันหมายถึง iframe ที่ซ้อนกันของหน้า a.html ภายใต้ http: //localhost/demo/iframe/iframea.html
ตัวอย่างเช่น: <iframe src = "http: //localhost/demo/iframe/iframeb.html" id = "iframea" name = "iframea"> ข้อมูลของทั้งสองหน้าสื่อสาร ตัวอย่างเช่นฉันต้องการเรียกฟังก์ชั่นในหน้าเด็กในหน้าหลัก a.html ซึ่งเป็นเรื่องง่ายสำหรับเราที่จะคิดว่า document.getElementById('iframeA').contentWindow.b(); ภายใต้ Google โดยที่ B เป็นฟังก์ชั่นในหน้าเด็ก b.html แต่มีปัญหาเกี่ยวกับการโทรนี้ที่ฉันต้องดิ้นรนมาเป็นเวลานานนั่นคือเนื่องจากฉันได้รายงานข้อผิดพลาดดังกล่าวภายใต้ Firefox ดังนี้:
B ไม่ใช่ฟังก์ชั่น แต่ฉันได้กำหนดฟังก์ชั่นดังกล่าวอย่างชัดเจนในหน้าย่อยดังนั้นทำไมข้อผิดพลาดดังกล่าวจึงเกิดขึ้น? หลังจากการวิเคราะห์อย่างรอบคอบและ Google ฉันพบว่ามีปัญหาที่ต้องเข้าใจ เมื่อ iframe ไม่ได้รับการโหลดฉันจะเรียกใช้งาน JS นี้และรายงานข้อผิดพลาดดังกล่าว ดังนั้นฉันจึงพยายามใช้ฟังก์ชั่น iframe.onload ภายใต้ Firefox เพื่อทดสอบ แน่นอนว่าไม่มีข้อผิดพลาดมันถูกต้องดังนั้นฉันจึงแน่ใจว่ามันเป็นปัญหานี้ ดังนั้นฉันต้องการเขียน IE และ Firefox Google เพื่อเขียนฟังก์ชั่นเพื่อยืนยันว่า iframe ได้รับการโหลดแล้ว! อันที่จริงให้ฟังก์ชั่นการโทรกลับเพื่อเรียกวิธีการข้างต้นของเรา
จากแนวคิดข้างต้นคุณสามารถเขียนรหัสเช่นนี้:
<iframe src = "http: //localhost/demo/iframe/iframeb.html" id = "iframea" name = "iframea"> </iframe> <div id="topName">topNdddddddddddddddddddddddddddddddddddddddddd</div> <script> function A(){ alert("A"); } var iframe = document.getElementById ('iframea'); iframeisload (iframe, function () {var obj = document.getElementById ('iframea'). contentWindow; obj.b ();}); ฟังก์ชั่น 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"); - มันง่ายมากที่จะเรียกฟังก์ชั่นของหน้าหลักในหน้าเด็ก เพียงทำสิ่งนี้และมันจะโอเค window.parent.A();
หน้าเด็กใช้ค่าขององค์ประกอบหน้าหลัก: window.parent.document.getElementById("topName").innerHTML และวิธีอื่น ๆ
สอง: การสื่อสารข้ามโดเมน iframe
IFRAME Cross-Domain Access โดยทั่วไปแบ่งออกเป็นสองสถานการณ์ อย่างแรกคือ cross-domain ที่มีโดเมนหลักเดียวกันและโดเมนย่อยที่แตกต่างกัน ประเภทที่สองคือ: โดเมนหลักที่แตกต่างกันข้ามโดเมน
1. มันเป็นโดเมนข้ามระหว่างโดเมนย่อยที่แตกต่างกันภายใต้โดเมนหลักเดียวกัน มันสามารถแก้ไขได้โดยการตั้งค่าโดเมนหลักเดียวกันผ่าน document.domain
ถ้าฉันมีโดเมน abc.example.com มีหน้าหนึ่งชื่อ abc.html และ iframe จะซ้อนกันในหน้าดังนี้: <iframe src = "http://def.example.com/demo/def.html" id = "iframe2" หน้า ABC.HTML เราทุกคนรู้ว่าเนื่องจากข้อ จำกัด ของนโยบายต้นกำเนิดเดียวกันของเบราว์เซอร์ความปลอดภัย JS จึงไม่สามารถใช้งานหน้าเว็บที่มีพอร์ตที่แตกต่างกันภายใต้โปรโตคอลที่แตกต่างกันภายใต้โดเมนที่แตกต่างกัน หากหน้าหลัก abc.html มีฟังก์ชั่น JS: function test(){console.log(1);}; ฉันต้องการเรียกฟังก์ชั่นนี้ในหน้าย่อยหรือโทร parent.test(); ด้วยวิธีนี้โดยดูที่ cross-domain ภายใต้ Firefox วิธีแก้ปัญหาคือการเพิ่ม document.domain = 'example.com' ที่ด้านบนของฟังก์ชั่น JS แต่ละฟังก์ชันและสามารถแก้ไขได้
รหัส ABC.HTML มีดังนี้:
<iframe src = "http://def.example.com/demo/def.html" id = "iframe2" style = "แสดง: ไม่มี;"> </iframe> // ฟังก์ชั่นที่เรียกหน้าหลัก
รหัส def.html มีดังนี้:
/** วิธีการของหน้าเด็กที่เรียกหน้าหลัก*/document.domain = 'example.com'; // window.top.test (); window.parent.test ();
หรือสองหน้านี้ฉันต้องการให้หน้าหลักเรียกหน้าเด็กดังนี้:
รหัส A.HTML มีดังนี้:
/** ฟังก์ชั่นที่ต้องการเรียกหน้าเด็กผ่านหน้าหลักของโดเมน*/document.domain = 'example.com'; var iframe = document.getElementById ('iframe2'); iframeisload (iframe, function () {var obj = iframe.contentWindow; obj.child () if (iframe.attachevent) {iframe.attachevent ('onload', function () {callback && callback ();}); } else {iframe.onload = function () {callback && callback (); -หากมีรหัสฟังก์ชั่นเด็กในหน้า def.html ตอนนี้:
document.domain = 'example.com'; function child () {console.log ('ฉันเป็นหน้าเด็ก');}คุณสามารถโทรข้ามโดเมนไม่ว่าจะเป็นหน้าเด็กที่เรียกหน้าหลักหรือหน้าหลักเรียกหน้าเด็ก ทุกอย่างโอเค!
2. มันเป็นโดเมนหลักที่แตกต่างกันและโดเมนข้าม
แม้ว่า Google จะมีวิธีการหลายวิธีสำหรับปัญหาข้ามโดเมนเกี่ยวกับโดเมนหลักที่แตกต่างกันรวมถึงวิธี location.hash วิธีการ window.name , HTML5 และ Flash ฯลฯ ฉันคิดว่าวิธีการ IFRAME ต่อไปนี้คุ้มค่ากับการเรียนรู้
ดังที่แสดงในรูปด้านล่าง: page request.html ของโดเมน A.Com (เช่น http://a.com/demo/ajax/ajaxproxy/request.html) ซ้อนกับ iframe ที่ชี้ไปที่โดเมน A.COM ซ้อนกันกับพร็อกซี. html ของโดเมน A.com
แนวคิด: ในการใช้หน้าคำขอ. html ภายใต้กระบวนการร้องขอโดเมน A.COM ภายใต้โดเมน B.Com คุณสามารถส่งพารามิเตอร์การร้องขอไปยังการตอบสนอง html ผ่าน URL และเริ่มต้นคำขอ AJAX จริงจากการตอบสนอง html ไปยัง process.php (response.html และ process.php ในที่สุดเนื่องจาก proxy.html และ request.html อยู่ในโดเมนเดียวกันคุณสามารถใช้ window.top เพื่อส่งคืนผลลัพธ์ใน request.html เพื่อเติมเต็มโดเมนข้ามจริง
ตกลงมาดูโครงสร้างหน้าก่อน
ภายใต้โดเมน A.COM มี:
request.html
proxy.html
ภายใต้โดเมน B.Com มี:
Response.html
process.php
มาดูหน้า request.html ดังนี้:
<! doctype html> <html> <head> <ditle> เอกสารใหม่ </title> </head> <body> <p id = "ผลลัพธ์"> ผลการตอบกลับจะถูกกรอกที่นี่ </p> <a id = "sendbtn" href = "javaScript: void (0)"> คลิกเพื่อส่ง cross-domain style = "display: none"> </iframe> <script> document.getElementById ('sendbtn'). onclick = function () {var url = 'http://b.com/demo/ajax/ajaxproxy/reponse.html', fn = 'getperson' 24} ', // นี่คือพารามิเตอร์ที่ร้องขอการเรียกกลับ = "การโทรกลับ"; // นี่คือฟังก์ชั่นการโทรกลับที่ดำเนินการหลังจากกระบวนการร้องขอทั้งหมดเสร็จสิ้นการดำเนินการ crossRequest การดำเนินการครั้งสุดท้าย (URL, FN, REQDATA, การโทรกลับ); // ส่งคำขอ} ฟังก์ชั่น CrossRequest (URL, FN, REQDATA, CALLBACK) {var Server = document.getElementById ('Serverif'); server.src = url + '? fn =' + encodeuricomponent (fn) + "& data =" + encodeuricomponent (reqdata) + "& callback =" + encodeuricomponent (การเรียกกลับ); } // ฟังก์ชั่นฟังก์ชั่นการโทรกลับ (ข้อมูล) {var str = "ชื่อของฉันคือ" + data.name + "ฉันคือ" + data.sex + "ฉันคือ" + data.age + "ปี"; document.getElementById ("ผลลัพธ์"). innerhtml = str; } </script> </body> </html> หน้านี้เกี่ยวกับการบอก Response.html: ฉันต้องการให้คุณดำเนินการวิธีที่คุณกำหนด GetPerson และใช้พารามิเตอร์ '{"id": 24}' ฉันให้คุณ Response.html รับผิดชอบอย่างหมดจดในการส่งชื่อวิธี CallBack ไปยัง Proxy.html พี่ชายคนต่อไป proxy.html สามารถเรียกใช้งานได้หลังจากได้รับชื่อวิธี CallBack เนื่องจาก proxy.html และ request.html อยู่ในโดเมนเดียวกัน
รหัส Response.html มีดังนี้:
<! doctype html> <html> <head> <dite> เอกสารใหม่ </title> </head> <body> <iframe id = "proxy"> </iframe> <script> // วิธีการทั่วไป AJAX request _request (reqData, url, url, callback) if (window.xmlhttprequest) {xmlhttp = ใหม่ xmlhttprequest (); } else {xmlhttp = new ActiveXObject ("microsoft.xmlhttp"); } xmlhttp.onreadyStateChange = function () {ถ้า (xmlhttp.readystate == 4 && xmlhttp.status == 200) {var data = xmlhttp.responsetext; การโทรกลับ (ข้อมูล); }} xmlhttp.open ('โพสต์', url); XMLHTTP.SetRequestHeader ("ประเภทเนื้อหา", "Application/JSON; charset = UTF-8"); xmlhttp.send (reqdata); } // วิธีการทั่วไปเพื่อรับฟังก์ชันพารามิเตอร์ URL _getQuery (คีย์) {var query = location.href.split ('?') [1], value = decodeuricomponent (query.split (คีย์ + "=") [1] .split ("&") [0]); ค่าส่งคืน; } // ส่งคำขอ AJAX ไปยัง process.php 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 และรับพารามิเตอร์และวิธีการคำขอจากนั้นออกคำขอ AJAX จริงไปยัง Process.php เซิร์ฟเวอร์จากนั้นส่งข้อมูลที่ส่งคืนจากเซิร์ฟเวอร์และชื่อฟังก์ชันการโทรกลับจาก request.html ไปยัง proxy.html
ถัดไปลองดูที่รหัส PHP ดังนี้ ซึ่งจริงๆแล้วเป็นเพียงการส่งคืนข้อมูล JSON:
<? php $ data = json_decode (file_get_contents ("php: // input")); ส่วนหัว ("เนื้อหาประเภท: แอปพลิเคชัน/json; charset = utf-8"); echo ('{"id":'. $ data-> id. ', "อายุ": 24, "sex": "boy", "name": "huangxueming"}');?>ในที่สุดก็มีรหัส proxy.html:
<! doctype html> <html> <head> <title> เอกสารใหม่ </title> </head> <body> <pristr> ฟังก์ชั่น _geturl (คีย์) {// วิธีการทั่วไปรับพารามิเตอร์ URL var query = location.href.split ("?") [1] "=") [1] .split ("&") [0]); ค่าส่งคืน; } (function () {var callback = _geturl ("callback"), data = _geturl ("data"); eval ("window.top." + decodeuricomponent (callback) + "(" + decodeuricomponent (data) + ")");}) (); </script> </body> </html>นี่เป็นขั้นตอนสุดท้าย ในที่สุดพร็อกซีได้รับชื่อฟังก์ชั่นการโทรกลับจาก request.html ผ่าน response.html และข้อมูลการตอบกลับที่ส่งโดยตรงจาก response.html และใช้ window.top เพื่อเรียกใช้ฟังก์ชันการโทรกลับที่กำหนดไว้ใน request.html
3. ปัญหาการปรับตัวสูงของ iframes
การปรับความสูงของ Iframe แบ่งออกเป็นสองประเภท: หนึ่งคือการปรับตัวภายใต้โดเมนเดียวกันและอีกประเภทหนึ่งคือการปรับตัวภายใต้โดเมนข้าม มาดูปัญหาการปรับตัวสูงในโดเมนเดียวกัน
1. ปัญหาเกี่ยวกับ iframes ที่ปรับตัวได้สูงในโดเมนเดียวกัน:
แนวคิด: รับองค์ประกอบ iframe ที่ซ้อนกันรับความสูงสุดท้ายของหน้าซ้อนกันผ่าน JavaScript จากนั้นตั้งค่าไว้ในหน้าหลักเพื่อให้ได้มัน
หากการสาธิตของเรามี iframe1.html และ iframe2.html
ต่อไปนี้เป็นรหัสต่อไปนี้:
<! doctype html> <html> <head> <title> เอกสารใหม่ </title> <style> *{margin: 0; padding: 0;} </style> </head> <body> <iframe src = "http://a.com/demo/ajax/iframeh id = "iframe"> </iframe> <script> window.onload = function () {var iframeid = document.getElementById ('iframe'); if (iframeid &&! window.opera) {ถ้า (iframeid.contentDocument && iframeid.contentDocument.body.offSetheight) {iframeid.height = iframeid.contentDocument.offSetheight; } อื่นถ้า (iframeid.document && iframeid.document.body.scrollheight) {iframeid.height = iframeid.document.body.scrollheight; }}} </script> </body> </html>iframe2.html
<! doctype html> <html> <head> <title> เอกสารใหม่ </title> <style> *{margin: 0; padding: 0;} </style> </head> <body> <div style = "ความสูง: 500px;"> </div> </body> </html>คุณสามารถตั้งค่าความสูงของหน้า iframe1 แบบไดนามิกเป็นความสูง iframe2
2. IFRames สามารถปรับเปลี่ยนได้สูงในโดเมน
ก่อนอื่นเรารู้ว่าเราไม่สามารถควบคุม cross-domain ของ iframes ด้วยวิธี JS ข้างต้นดังนั้นเราสามารถใช้คีย์กลางเพื่อทำรัง iframe2.html ใต้โดเมน B.Com บนหน้า iframe1.html ภายใต้โดเมน A.com ด้วยวิธีนี้ iframe1.html และ iframe3.html สามารถสื่อสารได้โดยไม่ต้องมีอุปสรรคเนื่องจากหน้า iframe2.html ทำรัง iframe3.html ดังนั้น iframe2.html สามารถเขียนค่า href ของ iframe3.html ใหม่
เนื้อหาใน iframe1:
เนื้อหา IFRAME1.HTML ส่วนใหญ่ยอมรับเนื้อหาที่ส่งจากหน้า IFRAME3.HTML และเสร็จสิ้นการดำเนินการที่เกี่ยวข้อง รหัส iframe1.html มีดังนี้:
<iframe src = "http://b.com/demo/ajax/iframeheight/iframe2.html" id = "iframe"> </iframe> ฟังก์ชั่น getifrdata (ข้อมูล) {ifr_el.style.height = data+"px"; } </script>เนื้อหาใน iframe2.html:
เนื้อหา IFRAME2.html ส่งผ่านค่าไปยังหน้า iframe3.html อย่างไร ฉันเพิ่งบอกว่าค่าถูกส่งผ่านไปยัง href ของหน้า iframe3.html ดังนั้นเพียงแค่แก้ไข src ของ iframe เนื่องจากไม่จำเป็นต้องรีเฟรชหน้า C จึงสามารถส่งผ่านไปยังหน้า IFRAME3.HTML โดยแฮช รหัสของ iframe2.html มีดังนี้:
<! doctype html> <html> <head> <title> เอกสารใหม่ </title> <style> *{margin: 0; padding: 0;} </style> </head> <body> <iframe id = "iframe" src = "http://a.com/demo/ajax/iframe var oldHeight = 0, ifr_el = document.getElementById ("iframe"); t && clearInterval (t); var t = setInterval (ฟังก์ชัน () {var height = document.body.scrollheight; ถ้า (oldheight! = ความสูง) {oldheight = ความสูง; ifr_el.src += '#' +oldheight;}}, 200); </script> </body> </html>คุณจะเห็นว่าโดยค่าเริ่มต้นความสูงของหน้า iframe1.html ฉันให้ iframe2.html คือ 200 พิกเซล แต่ใน iframe2.html ฉันให้ iframe3.html ความสูงของ iframe3.html คือ 230 พิกเซลดังนั้นภายใต้สถานการณ์ปกติ ตอนนี้ฉันต้องการได้รับความสูงของแถบเลื่อนใน iframe2.html, ส่งผ่านความสูงไปยัง SRC ผ่าน iframe3.html จากนั้นรับค่าความสูงในหน้า iframe3.html เพื่อส่งไปยัง iframe1.html (เพราะ iframe1.html ความสูงของตัวเองก็โอเค
ฟังก์ชั่นเดียวของหน้า iframe3.html คือการรับค่าที่ส่งผ่านโดยหน้า iframe2.html ผ่าน href และส่งผ่านไปยังหน้า iframe1.html ค่าที่ส่งผ่านไปยังหน้า iframe2.html สามารถตรวจสอบได้อย่างต่อเนื่องผ่านตัวจับเวลาเพื่อดูว่าสถานที่ที่มีการเปลี่ยนแปลงหรือไม่ แต่สิ่งนี้รู้สึกไม่มีประสิทธิภาพมาก อีกวิธีหนึ่งคือการฟังการเปลี่ยนแปลงของ HREF ผ่านเหตุการณ์ onhashchange (IE8+, Chrome5.0+, Firefox3.6+, Safari5.0+, OperA10.6+) ในเบราว์เซอร์ใหม่
รหัส IFRAME3.HTML มีดังนี้:
<script> var oldheight = 0; t && clearInterval (t); var t = setInterval (ฟังก์ชัน () {var height = location.href.split ('#') [1]; ถ้า (ความสูง && ความสูง! = oldHeight) {oldHeight = ความสูง; ถ้า (window.parent.parent.getifrdata) {window.parent.parent.parent.getifrdata </script>สิ่งนี้สามารถแก้ปัญหาการบรรลุความสูงของการปรับตัว iframe ผ่านโดเมนข้าม
4. สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาและการทำงานของทุกคน หากคุณมีคำถามใด ๆ โปรดฝากข้อความเพื่อพูดคุย