วิธีการสื่อสารระหว่าง iframe และไซต์แม่


185

เว็บไซต์ใน iframe ไม่ได้อยู่ในโดเมนเดียวกันแต่ทั้งคู่เป็นของฉันและฉันต้องการสื่อสารระหว่างiframeและกับเว็บไซต์แม่ เป็นไปได้ไหม?

คำตอบ:


307

ด้วยโดเมนที่ต่างกันจึงไม่สามารถเรียกวิธีการหรือเข้าถึงเอกสารเนื้อหาของ iframe ได้โดยตรง

คุณต้องใช้การส่งข้อความข้ามเอกสาร

ตัวอย่างเช่นในหน้าต่างด้านบน:

 myIframe.contentWindow.postMessage('hello', '*');

และใน iframe:

window.onmessage = function(e){
    if (e.data == 'hello') {
        alert('It works!');
    }
};

หากคุณกำลังโพสต์ข้อความจาก iframe ไปที่หน้าต่างหลัก

window.top.postMessage('hello', '*')

2
ขอบคุณ แต่น่าเสียดายที่มันไม่สามารถใช้ได้กับเบราว์เซอร์รุ่นเก่า
Danny Fox

106
window.onmesage = function()...ในแม่: ใน iframe:window.top.postMessage('hello', '*')
123444555621

3
มันไม่ใช่ข้อผิดพลาด ไฟล์ URL อาจไม่ปลอดภัยและเบราว์เซอร์กำลังดูแลพวกเขาอย่างระมัดระวัง ย้อนกลับไปในอดีตคุณสามารถใส่ลิงค์ไปยังfile://C:/Windows/system32/whateverหน้าเว็บและทำให้มันชี้ไปที่โฟลเดอร์ระบบของผู้ใช้ วันนี้เบราว์เซอร์ส่วนใหญ่ไม่สนใจการคลิกลิงก์เช่นนั้น เรียกใช้เว็บเซิร์ฟเวอร์และเข้าถึงรหัสของคุณผ่านทางนั้นและคุณจะเห็นข้อผิดพลาด diappear
Stijn de Witt

4
ตามแนวทางปฏิบัติที่ดีอย่าใช้ '*' กับเป้าหมายของคุณ ในความเป็นจริง MDN กล่าวว่า - "ให้เป้าหมายเฉพาะเจาะจงเสมอต้นไม่ใช่ * ถ้าคุณรู้ว่าเอกสารของหน้าต่างอื่นควรอยู่ที่ใดหากไม่ระบุเป้าหมายเฉพาะจะเป็นการเปิดเผยข้อมูลที่คุณส่งไปยังเว็บไซต์อันตรายที่น่าสนใจ"
rodiwa

2
เรายังสามารถใช้window.frames[index]เพื่อให้ได้กรอบเด็ก ( <iframe>, <object>, <frame>) getElementsByTagName("iframe")[index].contentWindowเทียบเท่ากับ ที่จะได้รับวัตถุหน้าต่างหลักจาก IFrames มันจะดีกว่าที่จะใช้window.parentเป็นwindow.topหมายถึงผู้ปกครองมากที่สุดบนหน้าต่าง
phoenisx

46

มันจะต้องอยู่ที่นี่เพราะคำตอบที่ได้รับการยอมรับจาก 2012

ในปี 2018 และเบราว์เซอร์สมัยใหม่คุณสามารถส่งเหตุการณ์ที่กำหนดเองจาก iframe ไปยังหน้าต่างหลัก

iframe:

var data = { foo: 'bar' }
var event = new CustomEvent('myCustomEvent', { detail: data })
window.parent.document.dispatchEvent(event)

ผู้ปกครอง:

window.document.addEventListener('myCustomEvent', handleEvent, false)
function handleEvent(e) {
  console.log(e.detail) // outputs: {foo: 'bar'}
}

PS: แน่นอนคุณสามารถส่งกิจกรรมในทิศทางตรงกันข้ามในลักษณะเดียวกัน

document.querySelector('#iframe_id').contentDocument.dispatchEvent(event)

1
สวัสดีฉันต้องอยู่ในโดเมนเดียวกันหรือไม่
Guillaume Harari


1
ควรสังเกตว่าdispatchEventได้รับการสนับสนุนในเบราว์เซอร์หลักทั้งหมด IE9 เป็นรุ่นแรกที่เปิดตัวดังนั้นระบบปฏิบัติการส่วนใหญ่จึงสามารถใช้งานได้ caniuse.com/#search=dispatchEvent
Dan Atkinson

1
ฉันไม่สามารถสื่อสารจากผู้ปกครองไปยัง iframe ด้วยวิธีนี้ได้
Avan

ใช่ฉันไม่สามารถใช้งานได้เช่นกัน iframe js กำลังโหลดหลังจากหน้าต่างหลักดังนั้นจึงไม่ได้รับ msg เมื่อส่ง มันใช้งานได้ตั้งแต่ iframe ถึงผู้ปกครองสำหรับฉันเท่านั้น
radtek

14

ห้องสมุดนี้รองรับ HTML5 postMessage และเบราว์เซอร์รุ่นเก่าที่มีการปรับขนาด + แฮชhttps://github.com/ternarylabs/porthole

แก้ไข: ตอนนี้ในปี 2014 การใช้งาน IE6 / 7 ค่อนข้างต่ำ IE8 และเหนือการสนับสนุนทั้งหมดpostMessageดังนั้นตอนนี้ฉันแนะนำให้ใช้แค่นั้น

https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage


ด้วยข้อแม้ที่ IE8 / 9 สนับสนุนเฉพาะสตริงcaniuse.com/#search=postmessage (ดูปัญหาที่ทราบ)
Harry

สิ่งนี้สามารถแก้ไขได้โดยการเข้ารหัสวัตถุเหตุการณ์ของคุณไปที่ json และถอดรหัสพวกเขาในอีกด้านหนึ่ง
codewandler

3

window.topคุณสมบัติควรจะสามารถที่จะให้สิ่งที่คุณต้องการ

เช่น

alert(top.location.href)

ดู http://cross-browser.com/talk/inter-frame_comm.html


10
เนื่องจาก iframe ไม่ได้อยู่ในโดเมนเดียวกันเขาจึงไม่สามารถเข้าถึงผู้ปกครองได้
Andreas Köberle


1

ใช้event.source.window.postMessageเพื่อส่งกลับไปยังผู้ส่ง

จาก Iframe

window.top.postMessage('I am Iframe', '*')
window.onmessage = (event) => {
    if (event.data === 'GOT_YOU_IFRAME') {
        console.log('Parent received successfully.')
    }
}

จากนั้นผู้ปกครองพูดกลับ

window.onmessage = (event) => {
    event.source.window.postMessage('GOT_YOU_IFRAME', '*')
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.