兩個窗口如何實現通信

From: https://blog.csdn.net/CRMEB/article/details/134398554

前言介紹
在工作中就出現的這種問題,開發的產品的頁面需要嵌入到公司中其他產品中,因爲是不同的產品,屬於不同的系統,最簡單的方式就是iframe和window.open()的方式,我選擇的是window.open()的方式,因爲實現的效果就是點擊某個按鈕才顯示該頁面,使用window.open()的方式對於佈局都比較好控制,這時就有個問題了。因爲開發產品頁面直接需要獲取該用戶在其他產品時的用戶信息和產品信息,就涉及到了如何傳遞信息的問題了

window.open()的參數介紹
對於window.open()一般可以設置三個參數,這裏就簡單介紹了,如果需要更深入的瞭解就請自己查找資料

第一個參數,打開新窗口的url地址

第二個參數,給新窗口的名字(name),並不是新窗口在窗口顯示的title,在窗口下,通過window.name的方式拿到

這裏也可以設置_self(在舊窗口打開新窗口),_blank(重新打開新窗口,默認就是該模式)
第三個參數,設置打開新窗口的寬高等

一般設置'left=100,top=100,width=400,height=400',四個參數,其他參數可能有瀏覽器兼容問題
1
返回值——新窗口的window引用

這時就有個疑問了,在設置第二參數時,我又想設置_self又想給新窗口設置name怎麼辦?

可以使用如下方式:

var targetWindow = window.open('', '_self')
targetWindow.name = 'demo'
targetWindow.location.href = 'http://localhost:8081/'
1
2
3
你會想這樣寫這麼麻煩,下面這麼寫不就很簡單啊

var targetWindow = window.open('http://localhost:8081/', '_self')
targetWindow.name = 'demo'
1
2
URL 的實際獲取是延遲進行的,並在當前腳本塊執行完畢後開始。窗口創建和引用資源的加載是異步進行的。

在第一種方法中並沒有url的加載,所以窗口是已經創建了,再給這個窗口設置的name。第二種方法有url的異步加載,該窗口並沒有被創建好,就給這個窗口設置name,自然就無效了。

1.使用url攜帶參數的形式
可能最容易想到的方式就是使用url上攜帶參數的形式了,但是這種方式對於傳遞多種數據是不方便的,而且安全性也是個問題

2.使用postMessage的方式(使用環境:Vue)
通過查找資料發現了這種比較有意思的方式,這種方式竟然對於跨域也是可以解決的,這不正合我意。

postMessage常用參數

第一個參數,就是傳遞的消息message,可以使用字符串,信息過多可以使用JSON.stringify()的方式
第二個參數,就是發送的url地址,也可以使用*來代替,但是不安全
發送方使用postMessage,接收方綁定message事件

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)
})
1
2
3
4
5
6
7
8
9
我就直接介紹跨域的方式如何使用,對於同源的方式也可以使用該方式,也有其他方式。

我想要的,

舊窗口把信息傳給新窗口
舊窗口

// 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>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
新窗口

// 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)
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
舊窗口可以向新窗口發信息,新窗口也可以發送信息給舊窗口
舊窗口

// 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>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
新窗口

//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)
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
看到這裏你可能發現有段代碼很怪,爲什麼有些數據聲明在return上面的,這麼做是因爲讓這個數據失去響應式,如果聲明在return內是有響應式的,這時this.targetWindow = window.open()在控制檯會出現跨域的報錯。原因是因爲給它賦值是打開子窗口的window,賦值會就會監聽targetWindow,就相當於在父窗口去對子窗口做操作,就造成了跨域的問題。

3.使用window.name的方式傳遞信息
利用window.open()的第二個參數,把信息傳給新窗口

舊窗口

window.open('http://localhost:8081/','要傳遞的信息')
1
新窗口

console.log(window.name)
1
總結
如果就是舊窗口傳遞信息給新窗口,不需要新窗口給舊窗口傳遞信息,且只傳一次,三種方式都可以,推薦使用第三種方式

如果想實現兩個窗口通信的話,就使用第二種方式

完整項目附件:點此下載
————————————————

版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

原文鏈接:https://blog.csdn.net/CRMEB/article/details/134398554

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章