Як спілкуватися між 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на веб-сторінку і зробити так, щоб вона вказувала прямо в системну папку користувача. Сьогодні браузери здебільшого ігнорують кліки на таких посиланнях. Запустіть веб-сервер і отримайте доступ до свого коду через це, і ви побачите, що помилки зникають.
— Штійн де Вітт

4
Як хороша практика, ніколи не використовуйте "*" для своєї цілі. Насправді, MDN каже: "Завжди надайте конкретну targetOrigin, а не *, якщо ви знаєте, де повинен знаходитися документ іншого вікна. Якщо не вказати конкретну ціль, розкриваються дані, які ви надсилаєте на будь-який зацікавлений шкідливий сайт".
— rodiwa

2
Ми навіть можемо використовувати window.frames[index]дочірній кадр ( <iframe>, <object>, <frame>), еквівалентний getElementsByTagName("iframe")[index].contentWindow. Щоб отримати об'єкт Parent Window від 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
Привіт, чи повинен я бути в одному домені, щоб це зробити?
— Гійом Харарі


1
Слід зазначити, що dispatchEventце підтримується у всіх основних браузерах. IE9 була першою версією, в яку вона з'явилася, тому більшість ОС зараз працює з нею. caniuse.com/#search=dispatchEvent
— Ден Аткінсон

1
Я не в змозі спілкуватися від батьків до iframe цим методом.
— Аван

Так, я також не можу змусити його працювати, iframe js завантажується після батьківського вікна, тому він не існує, щоб отримувати повідомлення при надсиланні. для мене це працює лише від iframe до батьківського.
— радтек

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 (Див. Відомі проблеми)
— Гаррі

це можна вирішити, кодуючи об’єкти події до json та декодуючи їх з іншого боку.
— кодовера



1

Використовуйте event.source.window.postMessageдля повернення відправнику.

Від Іфрейму

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', '*')
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.