简体   繁体   中英

How to communicate between iframe and the parent site?

The website in the iframe isn't located in the same domain , but both are mine, and I would like to communicate between the iframe and the parent site. Is it possible?

With different domains, it is not possible to call methods or access the iframe's content document directly.

You have to use cross-document messaging .

parent -> iframe

For example in the top window:

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

and in the iframe:

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

iframe -> parent

For example in the top window:

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

and in the iframe:

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

In 2018 and modern browsers you can send a custom event from iframe to parent window.

iframe:

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

parent:

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

PS: Of course, you can send events in opposite direction same way.

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

This library supports HTML5 postMessage and legacy browsers with resize+hash https://github.com/ternarylabs/porthole

Edit: Now in 2014, IE6/7 usage is quite low, IE8 and above all support postMessage so I now suggest to just use that.

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

Use event.source.window.postMessage to send back to sender.

From Iframe

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

Then from parent say back.

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

the window.top property should be able to give what you need.

Eg

alert(top.location.href)

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

You can also use

postMessage(message, '*') ;

After spending 2 days trying to get an iFrame posting messages back to the parent, a Vue application in my situation, I came across this excellent reference:

https://dev-bay.com/iframe-and-parent-window-postmessage-communication/

From the iframe to parent:

    const parentWindow = window.parent;
    class Message {
        constructor(type, body) {
          this.type = type;
          this.body = body;
        }
    };

    function sendMessage (windowObj, payload) {
        if(windowObj) {
          windowObj.postMessage(payload, "*");
        }
    };

    //Then call appropriately: 
    sendMessage(parentWindow, new Message("button-click", "Show Stats Overlay"));

In the parent, my Vue application mounted life cycle event, but reference the link for your own requirement:

    window.addEventListener("message", (e) => {
        var data = e.data;
        console.log("RECEIVED message from CHILD TO PARENT", data);
        
        var type = data.type;
        var body = data.body;

        if(type === "button-click" && body) {
          console.log("button-click RECEIVED FROM CHILD")
          //Additional functionality ...
        } else if (type === "text-msg" && body) {
          console.log("TEXT MESSAGE RECEIVED FROM CHILD");
          //Additional functionality ...
        }
      });

Please see reference for examples of communication from Parent to iFrame.

Hope this helps someone else.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM