The foreword 0.

We all know the tricks of the trade by heart. Now let’s do some practices that aren’t on the same TAB page or across domains.

1. localstorage

1.1 onstorage event

Localstorage is the storage space shared by the domain tags of the browser, so it can be used to achieve communication between multiple tags. Html5 has an event: onstorage, we add a listener on the window object to listen for changes: window.adDeventListener (‘storage’, (e) => console.log(e))

Note that this event is triggered only when the current page modiates localStorage. Modifying localStorage on the current page does not trigger the listener function. If you have to, rewrite your own method, or post your changes as you change them.

Example: js:

if(! localStorage.getItem('a')){
	localStorage.setItem('a'.1)}else{
	var s = localStorage.getItem('a')
	localStorage.setItem('a',+s+1)}window.addEventListener('storage', (e) => console.log(e))
Copy the code

Let’s create two new HTML pages called 1.html and 2.html and add the js above, so that every time we open or refresh the page we add 1 to a. Note that if you double-click to open a file, it is in the file:// protocol, and will not trigger the storage event, but will add 1 to a, so you can do a function to count how many times a local file was opened. If we open it with the server, our different TAB pages are communicating in real time.

2. Play the iframe

We all know that frames can cross domains, so let’s try it out. The following example is an HTML embedded iframe, of course you directly open the iframe file, does not make any sense

2.1 Using hash changes to transfer information to realize parent-child window communication (cross-domain)

Parent window: 1.html

html:

<iframe name="myIframe" src="http://localhost:1000/2.html"></iframe>
Copy the code

js:

var originURL = myIframe.location.href
var i = document.querySelector('iframe')
i.onload= function(){// This is the iframe loaded asynchronously
  i.src += '#aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
}
Copy the code

Child window: 2.html

window.onhashchange = function() {
    console.log(window.location.hash)
}
Copy the code

We open the parent window and find that the js of the child window is already running.

Now that it’s cross-domain, we can double click to open 1.html and find that it still works. In this example, double click to open and server to do the same

2.2 The parent invokes the js of the child page or vice versa

Parent note: Again based on the previous condition

var i = document.querySelector('iframe')
i.onload= function(){
myIframe.window.f();
}
Copy the code

Son: 2. HTML

function f(){
	console.log('this is 2.html')}Copy the code

Child tone parent: Child: 2.html

parent.fn1()
Copy the code

Father: 1. The HTML

function fn1(s){
	console.log('this is 1.html')}}Copy the code

Uncaught TypeError: parent. Fn1 is not a function. TypeError: parent

Uncaught DOMException: Uncaught DOMException: Blocked a frame with origin “null” from accessing a cross-origin frame., which can only be opened by the server

2.3 Window.name (Cross-domain)

Like vue and React prop, if you set the name of the iframe tag in the parent window, you can read it in the child window.

Parent window: 1.html

<iframe  name="myIframe" src="http://localhost:1000/2.html"></iframe>
Copy the code

Child window: 2.html

console.log(window.name)
Copy the code

Boy, feel free to double-click open it, there is an effect.

2.4 PostMessage (Cross-domain)

After H5, we added the window.postMessage() method for Windows. The first parameter is the data to send and the second parameter is the domain name.

Parent window: 1.html

<iframe id="test" name="myIframe" src="http://localhost:1000/2.html"></iframe>

//js
var frame = document.querySelector('iframe')
frame.onload = function(argument) {
	window.frames[0].postMessage('data from html1'.The '*');
}
Copy the code

Child window: 2.html

window.onmessage = function (e) {
	console.log(e.data)
}
Copy the code

It can cross domains, so you can double click to open it and see the effect.

The parent/child window above refers to the iframe tag in one HTML that introduces another HTML.

3. The two tabs in different domains communicate with each other

That is, two unrelated TAB pages communicate (for example, I open a Baidu and a Github), how to communicate?

Of course baidu and Github can communicate, we do not know, we have to ask their home development. As we already know, iframe can cross domains and localStorage can enable two TAB pages to communicate. Let’s try iframe to bridge two separate TAB pages. Note that bridge is one HTML and the other two tabs are two HTML files opened by the browser. You can create two different HTML files, or you can create two identical HTML files, and then double click to open them, or open them on the server, or just have two.

Let’s call the bridge iframe bridge.html. We open it with Node and listen on the local port 1000.


      
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>hi</h1>
  </body>
  <script type="text/javascript">
window.addEventListener("storage".function(ev){
    if (ev.key == 'info') {
        window.parent.postMessage(ev.newValue,The '*'); }});window.addEventListener('message'.function(e){
    // After receiving the message from the parent document, broadcast it to other homologous pages
    localStorage.setItem('info',e.data);
});
  </script>
</html>
Copy the code

Let’s do two more pages, which look like this. And then we can open it in n different ways, but it’s not homologous


      
<html>
<head>
	<title></title>
</head>
<body>
    <input id="ipt" type="text" name="">
    <button onclick="sub()">sub</button>
    <p id="cont"></p>
    <iframe src="http://localhost:1000/" style="display: none"></iframe>
</body>
<script type="text/javascript">
    var ipt = document.querySelector('#ipt')
    function sub(){
      document.querySelector('iframe').contentWindow.postMessage(ipt.value,The '*');
      cont.innerHTML +='I:+ ipt.value + '<br>'
      ipt.value = ' '
    }
    window.addEventListener('message'.function(e){
      if(e.data) cont.innerHTML +='对方:'+ e.data + '<br>'
      
    });
</script>
</html>
Copy the code

Then a simple chat will do. Give it a try. Plus websocket, but also non-source chat, the other can be set up at will.

Updates from 1 to 2 in real time that’s how it works, and vice versa.

4.MessageChannel

As the name suggests, the information channel. Allows us to create a new message channel and send data M via its two MessagePort properties, available in the Web Worker. You can print from the console, and you can see that there are two properties, portL1 and port2. A page embedded with iframe is most commonly used this way.

Like a pipe that goes in as it goes out, we can add a third argument to the PostMessage method:

var channel = new MessageChannel();
channel.port1.addEventListener("message".function(e){
    window.parent.postMessage(e,The '*',[channel.port2]);
    channel = null;
});
Copy the code

Deep copy

N different object types, okay? Ring reference? How to make it super easy to copy?

And yet it did:

var obj ={a:1.b:2.c: {d:3.e: [{f:1.g:2}},h:null}
obj.h = obj
var res 
new Promise(resolve= > {
    var channel = new MessageChannel();
    channel.port2.onmessage = ev= > resolve(ev.data);
    channel.port1.postMessage(obj);
  }).then(data= >{res = data})
Copy the code

The data is passed to the pipe, which sends back an identical copy of the data, implementing deep copy. We call it structured cloning, which handles object loop dependencies and most built-in objects. For example, postMessage is often used when sending messages to child Windows or webworkers to get data for processing without contaminating the original data.