How to communicate between two windows

Introduction

This kind of problem arises at work. The pages of the developed products need to be embedded into other products in the company. Because they are different products and belong to different systems, the simplest way is to use iframe and window.open(). I chose the window.open() method, because the effect is to click a certain button to display the page. Using window.open() method is easier to control the layout, and then there is a problem. Because developing product pages directly requires obtaining the user information and product information of the user in other products, it involves the issue of how to transmit information.

Introduction to parameters of window.open()

Generally, three parameters can be set for window.open(). Here is a brief introduction. If you need a more in-depth understanding, please look up the information yourself.

  • The first parameter, the url address to open the new window

  • The second parameter, the name given to the new window, is not the title displayed in the window of the new window. Under the window, it is obtained through window.name.

    • You can also set here_self (open a new window in the old window), _blank (reopen a new window, the default is this mode)
  • The third parameter sets the width and height of the new window to open.

一般设置'left=100,top=100,width=400,height=400',四个参数,其他参数可能有浏览器兼容问题

Return value - the window reference of the new window

At this time, there is a question. When setting the second parameter, what should I do if I want to set _self and also want to set a name for the new window?

You can use the following methods:

 var targetWindow = window.open('', '_self')
 targetWindow.name = 'demo'
 targetWindow.location.href = 'http://localhost:8081/'

You would think that it would be so troublesome to write like this, but wouldn’t it be very simple to write like this?

 var targetWindow = window.open('http://localhost:8081/', '_self')
 targetWindow.name = 'demo'

URL 的实际获取是延迟进行的,并在当前脚本块执行完毕后开始。窗口创建和引用资源的加载是异步进行的。

In the first method, the URL is not loaded, so the window has already been created, and then the name is set for the window. The second method involves asynchronous loading of the URL. The window has not been created, so just setting a name to the window will naturally be invalid.

1. Use the form of url carrying parameters

Perhaps the easiest way to think of is to use the form of carrying parameters on the URL, but this method is inconvenient for transmitting multiple types of data, and security is also a problem.

2. How to use postMessage (usage environment: Vue)

I found this interesting method by searching for information. This method can also be solved for cross-domain problems. This is not what I want.

postMessage common parameters

  • The first parameter is the message passed. You can use a string. If there is too much information, you can use JSON.stringify().
  • The second parameter is the URL address sent. You can also use * instead, but it is not safe.

The sender uses postMessage and the receiver binds the message event

 window.addEventListener("message",(e) => {
     // 判断是否是旧窗口发过来的,这个if判断是必须的,然后会多接收一些不想接收的消息,就是信息还没有发送过来,绑定message事件会有默认信息
     if (e.origin !== "http://localhost:8080") return;
     // e.data——接收到的信息
     // e.origin——发送发的url地址,如果没有if判断,就会返回接收方的url(默认信息)
     // e.source——发送方的window引用,如果没有if判断,就会返回接收方的window(默认信息)
     // e.origin和e.source结合可以让接收方向发送方发送信息,从而达到双向通信
     console.log(e.data)
  })

I will directly introduce how to use the cross-domain method. This method can also be used for the same-origin method, and there are other methods.

what i want,

The old window passes information to the new window

old window

 // http://localhost:8080/
 <template>
   <div id="app">
     <button @click="open">打开新窗口</button>
   </div>
 </template>
 export default {
   name: 'App',
   data () {
     this.targetWindow = null
     return {
     }
   },
   methods: {
     open() {
       this.targetWindow = window.open('http://localhost:8081/', '_blank', 'left=100,top=100,width=400,height=400')
       // 为什么加定时器,主要是为了防止window.open()异步加载,页面没有加载出来,就把消息发送出去了,有更好的方式也可以使用其他方式
       setTimeout(() => {
         this.targetWindow.postMessage('旧窗口向新窗口发送的消息', 'http://localhost:8081/')
       }, 1000)
     }
   }
 }
 </script>

new window

 // http://localhost:8081/
 <template>
   <div id="app">
     新窗口
   </div>
 </template>
 export default {
   name: 'App',
   mounted() {
     window.addEventListener("message",(e) => {
       if (e.origin !== "http://localhost:8080") return;
        //发送方发送的信息
       console.log(e.data)
     })
   }
 }

The old window can send messages to the new window, and the new window can also send messages to the old window.

old window

 // http://localhost:8080/
 <template>
   <div id="app">
     <button @click="open">打开新窗口</button>
     <button @click="sendNew">向新窗口传消息</button>
     旧窗口接收到的信息:{
   
   { text }}
   </div>
 </template>
 export default {
   name: 'App',
   data () {
     this.targetWindow = null
     return {
       text: ''
     }
   },
   mounted() {
     window.addEventListener('message',(e) => {
       if (e.origin !== "http://localhost:8081/") return;
       console.log(e.data)
       this.text += e.data
     })
   },
   methods: {
     open() {
       this.targetWindow = window.open('http://192.168.3.76:8081/', '_blank', 'left=100,top=100,width=400,height=400')
       setTimeout(() => {
         this.targetWindow.postMessage('旧窗口向新窗口发送的消息', 'http://192.168.3.76:8081/')
       }, 1000)
     },
     sendNew() {
       this.targetWindow.postMessage('旧窗口通过按钮发送给新窗口的消息', 'http://localhost:8081/')
     }
   }
 }
 </script>

new window

 //http://localhost:8081/
 <template>
   <div id="app">
     新窗口
     <button @click="sendOld">向旧窗口发送消息</button>
     <!-- 接收旧窗口发送的消息 -->
     接收旧窗口发送的消息:{
   
   { text }}
   </div>
 </template>
 export default {
   name: 'App',
   components: {
     
   },
   data() {
     this.oldWindow = null
     this.oldOrigin = null
     return {
       text: ''
     }
   },
   mounted() {
     window.addEventListener("message",(e) => {
       if (e.origin !== "http://localhost:8080") return;
       this.text += e.data
       this.oldWindow = e.source
       this.oldOrigin = e.origin
     })
     console.log(window.name)
   },
   methods: {
     sendOld() {
       this.oldWindow.postMessage('新窗口通过按钮给旧窗口发送的消息', this.oldOrigin)
     }
   }
 }

When you see this, you may find that there is a strange piece of code. Why are some data declared above return? This is because the data loses responsiveness. If the declaration is responsive within return, then this.targetWindow = window .open() will cause a cross-domain error in the console. The reason is that assigning it a value opens the window of the child window, and the assignment will listen to the targetWindow, which is equivalent to operating the child window in the parent window, causing cross-domain problems.

3. Use window.name to pass information

Use the second parameter of window.open() to pass information to the new window

old window

 window.open('http://localhost:8081/','要传递的信息')

new window

 console.log(window.name)

Summarize

If the old window transmits information to the new window, and the new window does not need to transmit information to the old window, and it is only transmitted once, all three methods are available, and the third method is recommended.

If you want to achieve communication between two windows, use the second method

Full project attachment:Click here to download

Guess you like

Origin blog.csdn.net/CRMEB/article/details/134398554