¿Cómo comunicarse entre iframe y el sitio principal?


193

El sitio web en el iframe no está ubicado en el mismo dominio , pero ambos son míos, y me gustaría comunicarme entre el iframey el sitio principal. ¿Es posible?

Respuestas:


322

Con diferentes dominios, no es posible llamar a métodos o acceder directamente al documento de contenido del iframe.

Tienes que utilizar la mensajería entre documentos .

Por ejemplo en la ventana superior:

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

y en el iframe:

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

Si está publicando un mensaje desde iframe a la ventana principal

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

2
gracias, pero lamentablemente no funciona en navegadores antiguos.
Danny Fox

106
En los padres: window.onmesage = function().... En el iframe:window.top.postMessage('hello', '*')
user123444555621

4
No es un error. Las URL de archivos pueden ser muy inseguras y los navegadores las tratan con cada vez más cuidado. En los viejos tiempos, podía poner un enlace a file://C:/Windows/system32/whateveruna página web y hacer que apuntara directamente a la carpeta del sistema del usuario. En la actualidad, los navegadores ignoran en su mayoría los clics en enlaces como ese. Ejecute un servidor web y acceda a su código a través de él y verá que los errores desaparecen.
Stijn de Witt

4
Como buena práctica, nunca use el '*' para su objetivo. De hecho, MDN dice: "Proporcione siempre un origen de destino específico, no *, si sabe dónde debe ubicarse el documento de la otra ventana. No proporcionar un destino específico revela los datos que envía a cualquier sitio malicioso interesado".
rodiwa

2
Incluso podemos usar window.frames[index]para obtener child frame ( <iframe>, <object>, <frame>), equivalente a getElementsByTagName("iframe")[index].contentWindow. Para obtener el objeto de la ventana principal de IFrames, es mejor usarlo window.parent, ya que window.toprepresenta la ventana principal más importante
phoenisx

49

Debe estar aquí, porque respuesta aceptada de 2012

En 2018 y en los navegadores modernos, puede enviar un evento personalizado desde iframe a la ventana principal.

iframe:

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

padre:

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

PD: Por supuesto, puede enviar eventos en la misma dirección opuesta.

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

2
Hola, ¿tengo que estar en el mismo dominio para hacerlo?
Guillaume Harari


1
Cabe señalar que dispatchEventes compatible con todos los principales navegadores. IE9 fue la primera versión en la que vino, por lo que la mayoría de los sistemas operativos ahora funcionan con él. caniuse.com/#search=dispatchEvent
Dan Atkinson

1
No puedo comunicarme de padre a iframe con este método.
Avan

Sí, tampoco puedo hacer que funcione, el iframe js se está cargando después de la ventana principal, por lo que no está allí para recibir el mensaje cuando se envía. solo funciona de iframe a padre para mí.
radtek

14

Esta biblioteca es compatible con HTML5 postMessage y navegadores heredados con cambio de tamaño + hash https://github.com/ternarylabs/porthole

Editar: Ahora, en 2014, el uso de IE6 / 7 es bastante bajo, IE8 y, sobre todo, el soporte, postMessagepor lo que ahora sugiero usarlo.

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


Con la advertencia de que IE8 / 9 solo admite cadenas caniuse.com/#search=postmessage (Ver problemas conocidos)
Harry

esto se puede solucionar codificando sus objetos de evento en json y decodificándolos en el otro lado.
codewandler


3

Úselo event.source.window.postMessagepara enviar de vuelta al remitente.

Desde Iframe

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

Luego, de los padres, responda.

window.onmessage = (event) => {
    event.source.window.postMessage('GOT_YOU_IFRAME', '*')
}

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.