preface

At first glance a very simple API, only when you really use it, you will know the pit inside. Using window.postMessage helps us communicate securely across sources. The basic principle is that cross-document messages are sent via postMessage, message is used for listening, and message events are triggered when cross-document messages are received

grammar

targetWindow.postMessage(message, targetOrigin, [transfer]);

targetWindow: A reference to a target window, such as the window object returned by executing window.open, the reference to window.opener that opens the current window, the contentWindow property of iframe, or the window.frames Message with a named or numeric index: Data sent to the target window targetOrigin: Specifies the window to receive the message event. The value can be either a URI or the string “*” (for unrestricted).

If you know exactly which window the message should be sent to, always provide a targetOrigin with the exact value, not *. Not providing an exact target will result in data being leaked to any malicious site interested in the data.

Transfer: Optional (this item is not explained in this article) is a string of Transferable objects that are passed simultaneously with Message. Ownership of these objects is transferred to the receiver of the message, and ownership is no longer retained by the sender.

use

This article uses VScode’s Live Server to start local services

Send messages to yourself

Of course that doesn’t make any sense, but just to show you the parameters of the event object for the onMessage event, okay

/ / http://127.0.0.1:5500/A.html
const msg = {
    name: "mayoha"
  }
window.postMessage(msg, "http://127.0.0.1:5500")
window.addEventListener("message".(e) = > {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})
Copy the code

The event object of the onMessage event handler contains three important pieces of information: data: the data passed as the first argument to the postMessage origin: the document from which the message was sent The Window proxy object that sends the message

A opens B, and B sends data to A

// A.html
window.addEventListener("message".(e) = > {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})
// Automatic calls to open will be blocked by the browser and need to be manually cancelled
// Add a click event to open the new window manually
window.open("http://127.0.0.1:5501/B.html"."B")
Copy the code
// B.html
const msg = {
  name: "B"
}
const opener = window.opener
opener.postMessage(msg, "http://127.0.0.1:5500")
// Here is the connection between targetWindow and URI
// URI must be the URI of the opener window
This means that if you open page B from one of the pages in http://127.0.0.1:5500, you can successfully send cross-document messages
// If the URI is changed to "*", it means that any page opened on page B will receive the information transmitted on page B
Copy the code

A opens B and sends data to B

// A.html
<button onclick="openB()">open B</button>
const msg = {
    name: "A"
  }
function openB() {
  const open = window.open("http://127.0.0.1:5501/B.html"."B")
  setTimeout(() = > {
    open.postMessage(msg, "http://127.0.0.1:5501")},1000)}// Why call postMessage in setTimeout
// Because the remote URL is not loaded immediately after the window.open() method is called, the loading process is asynchronous.
// The actual loading of the URL is deferred until the end of the current script block. Windows are created and associated resources are loaded asynchronously.
// The message is sent before the page of B is opened, so B cannot receive the message
// Of course setTimeout is not a good method, just for demonstration purposes
Copy the code
// B.html
window.addEventListener("message".(e) = > {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})
Copy the code

Page A opens page B. After page B is loaded, page B will postMessage A message to page A. After page A receives the message, page B will postMessage the message to page B. Welcome to propose A better idea

// A.html
const msg = {
  name: "A"
}
var open = window.open("http://127.0.0.1:5501/B.html"."B")
function openB() {
  open = window.open("http://127.0.0.1:5501/B.html"."B")}window.addEventListener("message".(e) = > {
  if(e.origin === "http://127.0.0.1:5501") {
    open.postMessage(msg, "http://127.0.0.1:5501")}})Copy the code
// B.html
const opener = window.opener
opener.postMessage(msg, "http://127.0.0.1:5500")
window.addEventListener("message".(e) = > {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})
Copy the code

Use in Iframe

The father the son

// a.html (parent)
<iframe src="http://127.0.0.1:5501/B.html" frameborder="1" id="Bframe"></iframe>
const msg = {
    name: "A"
  }
window.onload = () = > {
  // Automatic calls must be placed in onload, event calls do not
  // let frame = document.querySelector("#Bframe").contentWindow
  let frame = window.frames[0]
  frame.postMessage(msg, "http://127.0.0.1:5501")}Copy the code
// B.html
window.addEventListener("message".(e) = > {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})
Copy the code

Child the parent

// a.html (parent)
<iframe src="http://127.0.0.1:5501/B.html" frameborder="1" id="Bframe"></iframe>
window.addEventListener("message".(e) = > {
  console.log(e.data)
  console.log(e.origin)
  console.log(e.source)
})
Copy the code
// B.html
const msg = {
  name: "B"
}
window.top.postMessage(msg, "http://127.0.0.1:5500")
Copy the code

The last

Please correct any mistakes if any