React常見跨窗口通信方式實(shí)例詳解
iframe
跨窗口通信就是在嵌套了iframe的時(shí)候,實(shí)現(xiàn)iframe與父窗口的通信。
什么是iframe
- 它是一個(gè)
html標(biāo)簽,它可以將一個(gè)網(wǎng)站作為一個(gè)dom元素,嵌入到另一個(gè)網(wǎng)站中。 iframe具有自己的window與document對(duì)象。
使用場(chǎng)景
- 比如公司開發(fā)了一個(gè)完整的網(wǎng)站,需要在另一個(gè)項(xiàng)目中去使用。比如直播功能,一些插件,這時(shí)候就可以使用
iframe嵌入的方式。減少了重復(fù)開發(fā)的時(shí)間,需要修改界面的時(shí)候,也只需要修改一份代碼即可。 - 微應(yīng)用,微應(yīng)用也有很多是使用
iframe來實(shí)現(xiàn)。
同源策略
當(dāng)兩個(gè)網(wǎng)站同時(shí)滿足:同協(xié)議+同域名+同端口的時(shí)候。
當(dāng)iframe與父窗口同源時(shí)
- 父窗口可以對(duì)
iframe進(jìn)行完全訪問,如window,document,location等對(duì)象的訪問。 - 父窗口可以調(diào)用
iframe的全局函數(shù)。 - 父窗口可以修改
iframe的元素內(nèi)容
效果圖
index1.html嵌套同源的index2.html
html1
<body>
<h1>html-1</h1>
<iframe src="http://127.0.0.1:3000/index2.html" frameborder="0"></iframe>
<script>
const iframe = document.querySelector("iframe");
iframe.onload = function () {
console.log(iframe)
// 獲取iframe的window對(duì)象
const iWindow = iframe.contentWindow;
// 獲取iframe的document對(duì)象
const iDocument = iframe.contentDocument;
console.log(iWindow)
console.log(iWindow.location)
iWindow.say()
iDocument.body.innerHTML = "<h1>this is html-1</h1>"
}
</script>
</body>
html2
<body>
<h1>html-2</h1>
<script>
function say() {
console.log("saying!!!")
}
</script>
</body>
效果圖
index1.html嵌套同源的index2.html
發(fā)現(xiàn)子iframe的window,document,location對(duì)象,以及子iframe的全局方法都可以訪問。

當(dāng)iframe與父窗口不同源時(shí)
- 父窗口無法訪問
iframe的window的所有屬性與方法。 - 父窗口無法訪問
iframe的document。 - 無法調(diào)用
iframe的全局方法。
效果圖


跨窗口通信
一:通過window.parent、frames、top
window.frames:獲取子iframe的列表,與document.querySelector("iframe")一樣
window.parent:獲取父window的引用
window.top:獲取最頂層窗口的window引用
上一節(jié)我們講到,當(dāng)iframe同源時(shí),不同窗口可以拿到對(duì)方的window對(duì)象,以及全局方法,那么我們可以利用全局方法來實(shí)現(xiàn)不同window窗口的通信。
html1
<body>
<h1>html-1</h1>
<div>
<button onclick="send(Math.random(1))">發(fā)送數(shù)據(jù)給html2</button>
</div>
<iframe src="http://127.0.0.1:3000/index2.html" frameborder="0"></iframe>
<script>
const iframe = document.querySelector("iframe");
let send;
iframe.onload = function () {
// 獲取iframe的window對(duì)象
const iWindow = iframe.contentWindow;
// 獲取iframe的document對(duì)象
const iDocument = iframe.contentDocument;
function receive(value) {
console.log("這是html1,來了一條數(shù)據(jù):", value)
}
send = function (value) {
iWindow.receive(value)
}
}
</script>
</body>
html2
<body>
<h1>html-2</h1>
<div>
<button onclick="send(Math.random(1))">發(fā)送數(shù)據(jù)給html1</button>
</div>
<script>
function receive(value) {
console.log("當(dāng)前是html2,收到一條數(shù)據(jù):", value)
}
function send(value) {
window.parent.receive(value)
}
</script>
</body>
效果圖

同理,window.top也可以這樣通信
二:window.postMessage
postMessage支持不同窗口之間的通信,即使是非同源的情況。
發(fā)送數(shù)據(jù)
當(dāng)需要使用給其他窗口(window)發(fā)送數(shù)據(jù)時(shí),需要調(diào)用對(duì)方window的postMessage方法。
該方法接收兩個(gè)參數(shù)
- 參數(shù)一:需要發(fā)送的數(shù)據(jù),數(shù)據(jù)最后為字符串形式,因?yàn)镮E只支持字符串?dāng)?shù)據(jù)。
- 參數(shù)二:接收方的地址(協(xié)議+域名+端口)
接收數(shù)據(jù)
監(jiān)聽message事件
該事件對(duì)象包含接收的數(shù)據(jù),以及發(fā)送方的地址等信息。
html1
<body>
<h1>html-1</h1>
<div>
<button onclick="send(Math.random(1))">發(fā)送數(shù)據(jù)給html2</button>
</div>
<iframe src="http://127.0.0.1:3001/index2.html" frameborder="0"></iframe>
<script>
const iframe = document.querySelector("iframe");
let send;
iframe.onload = function () {
// 獲取iframe的window對(duì)象
const iWindow = iframe.contentWindow;
send = function (value) {
iWindow.postMessage("wuwuwuw", "http://127.0.0.1:3001")
}
}
window.addEventListener("message", function (event) {
if (event.origin != 'http://127.0.0.1:3001') {
// 過濾指定地址的信息
return;
}
if (window == event.source) {
// 頁面初始化的時(shí)候會(huì)被瀏覽器觸發(fā)一次message,在這里根據(jù)發(fā)送方地址進(jìn)行過濾
return
}
console.log("html1收到的數(shù)據(jù) " + event.data);
})
</script>
</body>
html2
<body>
<h1>html-2</h1>
<div>
<button onclick="send(Math.random(1))">發(fā)送數(shù)據(jù)給html1</button>
</div>
<script>
function receive(value) {
console.log("當(dāng)前是html2,收到一條數(shù)據(jù):", value)
}
function send(value) {
window.parent.postMessage(value, "http://127.0.0.1:3000")
}
window.addEventListener("message", function (event) {
if (event.origin != 'http://127.0.0.1:3000') {
// 過濾指定地址的信息
return;
}
if (window == event.source) {
// 頁面初始化的時(shí)候會(huì)被瀏覽器觸發(fā)一次message,在這里根據(jù)發(fā)送方地址進(jìn)行過濾
return;
}
console.log("html2收到的數(shù)據(jù) " + event.data);
})
</script>
</body>
效果圖

其他通信方法
- 使用soket,需要后端支持
- 使用本地存儲(chǔ),監(jiān)聽本地存儲(chǔ)的數(shù)據(jù)變化
以上就是React常見跨窗口通信方式實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于React跨窗口通信方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React項(xiàng)目中axios的封裝與API接口的管理詳解
Axios是一個(gè)npm軟件包,允許應(yīng)用程序?qū)TTP請(qǐng)求發(fā)送到Web API,下面這篇文章主要給大家介紹了關(guān)于React項(xiàng)目中axios的封裝與API接口的管理的相關(guān)資料,需要的朋友可以參考下2021-09-09
react實(shí)現(xiàn)antd線上主題動(dòng)態(tài)切換功能
這篇文章主要介紹了react實(shí)現(xiàn)antd線上主題動(dòng)態(tài)切換功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
使用React?Router?v6?添加身份驗(yàn)證的方法
這篇文章主要介紹了使用React?Router?v6?進(jìn)行身份驗(yàn)證完全指南,本文將演示如何使用React?Router?v6創(chuàng)建受保護(hù)的路由以及如何添加身份驗(yàn)證,需要的朋友可以參考下2022-05-05
一篇文章教你用React實(shí)現(xiàn)菜譜系統(tǒng)
本篇文章主要介紹了React實(shí)現(xiàn)菜譜軟件的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2021-09-09

