Как общаться между iframe и родительским сайтом?

185

Веб-сайт в iframe не находится в одном домене , но оба они мои, и я хотел бы установить связь между iframeродительским сайтом и. Является ли это возможным?

Дэнни Фокс
источник

Ответы:

309

Для разных доменов невозможно вызвать методы или получить прямой доступ к документу содержимого iframe.

Вы должны использовать обмен сообщениями между документами .

Например в верхнем окне:

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

и в фрейме:

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

Если вы отправляете сообщение из iframe в родительское окно

window.top.postMessage('hello', '*')
user123444555621
источник
2
спасибо, но, к сожалению, это не работает в старых браузерах.
Дэнни Фокс
106
В родителю: window.onmesage = function().... В window.top.postMessage('hello', '*')
фрейме
3
Это не ошибка. URL-адреса файлов могут быть очень небезопасными, и браузеры обращаются с ними со все возрастающей осторожностью. В старые времена вы могли поместить ссылку file://C:/Windows/system32/whateverна веб-страницу и указать ее прямо в системной папке пользователя. В наши дни браузеры в основном игнорируют нажатия на подобные ссылки. Запустите веб-сервер и получите доступ к своему коду через него, и вы увидите сообщение об ошибках.
Стейн де Витт
4
Как хорошая практика, никогда не используйте «*» для вашей цели. На самом деле, MDN говорит: «Всегда указывайте конкретный targetOrigin, а не *, если вы знаете, где должен находиться документ другого окна. Если вы не укажете конкретную цель, обнаружатся данные, которые вы отправляете на любой заинтересованный вредоносный сайт».
Родива
2
Мы можем даже использовать, window.frames[index]чтобы получить child frame ( <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)
Незнакомец в Q
источник
1
Здравствуйте, я должен быть на том же домене, чтобы сделать это?
Гийом Харари
1
stackoverflow.com/questions/25098021/…
Незнакомец в Q
1
Следует отметить, что dispatchEventподдерживается во всех основных браузерах. IE9 была первой версией, в которой он появился, поэтому большинство ОС теперь работают с ним. caniuse.com/#search=dispatchEvent
Дэн Аткинсон
1
Я не могу общаться с родителями в iframe с помощью этого метода.
Аван,
Да, я тоже не могу заставить его работать, iframe js загружается после родительского окна, поэтому он не получает сообщение при отправке. это работает только от iframe до parent для меня.
Радтек
14

Эта библиотека поддерживает HTML5 postMessage и устаревшие браузеры с изменением размера + хеш https://github.com/ternarylabs/porthole

Изменить: Теперь в 2014 году, использование IE6 / 7 довольно низкое, IE8 и, прежде всего, поддержка, postMessageпоэтому я предлагаю просто использовать это.

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

jpillora
источник
С оговоркой, что 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

sambomartin
источник
10
Поскольку iframe не находится в том же домене, он не может получить доступ к его родителю.
Андреас Кёберле
1

Вы также можете использовать

postMessage(message, '*');

gonzarodriguezt
источник
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', '*')
}
Бинь Хо
источник