JavaScript常見的跨標簽頁通信方式總結(jié)
引言
跨標簽頁通信是指在瀏覽器中的不同標簽頁之間進行數(shù)據(jù)傳遞和通信的過程。在傳統(tǒng)的Web開發(fā)中,每個標簽頁都是相互獨立的,無法直接共享數(shù)據(jù)。然而,有時候我們需要在不同的標簽頁之間進行數(shù)據(jù)共享或者實現(xiàn)一些協(xié)同操作,這就需要使用跨標簽頁通信來實現(xiàn)。
常見的跨標簽頁方案如下
- BroadCast Channel
- Service Worker
- LocalStorage window.onstorage 監(jiān)聽
- window.open、window.postMessage
- Shared Worker 定時器輪詢( setInterval )
- IndexedDB 定時器輪詢( setInterval )
- cookie 定時器輪詢( setInterval )
- Websocket
本文先介紹前面4種
BroadCast Channel
Broadcast Channel API 可以實現(xiàn)同源下瀏覽器不同窗口,Tab 頁,frame 或者 iframe 下的(通常是同一個網(wǎng)站下不同的頁面) 之間的簡單通訊。
通過創(chuàng)建一個監(jiān)聽某個頻道下的 BroadcastChannel對象,你可以接收發(fā)送給該頻道的所有消息。一個有意思的點是,你不需要再維護需要通信的 iframe 或 worker 的索引。它們可以通過構(gòu)造 BroadcastChannel 來簡單地“訂閱”特定頻道,并在它們之間進行全雙工(雙向)通信。

示例
通過創(chuàng)建一個廣播頻道,并在不同的標簽頁中監(jiān)聽該頻道,可以實現(xiàn)跨標簽頁通信。
例如,在一個標簽頁中發(fā)送消息:
const channel = new BroadcastChannel('myChannel');
channel.postMessage('Hello from Tab 1!');
在另一個標簽頁中接收消息:
const channel = new BroadcastChannel('myChannel');
channel.onmessage = function(event) {
console.log(event.data); // 輸出:Hello from Tab 1!
};
可以通過調(diào)用 BroadcastChannel 對象的 close()方法,可以離開頻道。這將斷開該對象和其關(guān)聯(lián)的頻道之間的聯(lián)系,并允許它被垃圾回收。
// 斷開頻道連接 channel.close();
Service Worker
Service worker 本質(zhì)上充當(dāng) Web 應(yīng)用程序、瀏覽器與網(wǎng)絡(luò)(可用時)之間的代理服務(wù)器。這個 API 旨在創(chuàng)建有效的離線體驗,它會攔截網(wǎng)絡(luò)請求并根據(jù)網(wǎng)絡(luò)是否可用來采取適當(dāng)?shù)膭幼?、更新來自服?wù)器的的資源。它還提供入口以推送通知和訪問后臺同步 API。
Service worker 是一個注冊在指定源和路徑下的事件驅(qū)動worker。它采用 JavaScript 文件的形式,控制關(guān)聯(lián)的頁面或者網(wǎng)站,攔截并修改訪問和資源請求,細粒度地緩存資源。你可以完全控制應(yīng)用在特定情形(最常見的情形是網(wǎng)絡(luò)不可用)下的表現(xiàn)。
使用 ServiceWorkerContainer.register() 方法首次注冊 service worker。如果注冊成功,service worker 就會被下載到客戶端并嘗試安裝或激活,這將作用于整個域內(nèi)用戶可訪問的 URL,或者其特定子集。
示例
index.html
<body>
<h1>頁面一</h1>
<button>發(fā)送</button>
<script>
navigator.serviceWorker.register('./sw.js')
.then(() => {
console.log("service worker 注冊成功");
});
document.querySelector("button").onclick = function () {
navigator.serviceWorker.controller.postMessage('hello');
}
</script>
</body>
index2.html
<body>
<h1>頁面二</h1>
<script>
navigator.serviceWorker.register('./sw.js')
.then(() => {
console.log("service worker 注冊成功");
});
navigator.serviceWorker.onmessage = function ({ data }) {
console.log(data);
}
</script>
</body>
sw.js
self.addEventListener("message",async event=>{
const clients = await self.clients.matchAll();
clients.forEach(function(client){
client.postMessage(event.data)
});
});
LocalStorage window.onstorage
存儲在 localStorage 的數(shù)據(jù)可以長期保留;而當(dāng)頁面會話結(jié)束——也就是說,當(dāng)頁面被關(guān)閉時,存儲在 sessionStorage 的數(shù)據(jù)會被清除。
另外,localStorage 中的鍵值對總是以字符串的形式存儲。 (需要注意,和 js 對象相比,鍵值對總是以字符串的形式存儲意味著數(shù)值類型會自動轉(zhuǎn)化為字符串類型).
當(dāng)存儲區(qū)域(localStorage 或 sessionStorage)被修改時,將觸發(fā) storage 事件。
由事件監(jiān)聽器發(fā)送給回調(diào)函數(shù)的事件對象有幾個屬性如下:
| Property | Type | Description |
|---|---|---|
| target 只讀 | [EventTarget] | 事件目標 (DOM 樹中的最大目標) |
| type 只讀 | [DOMString] | 事件的類型 |
| bubbles 只讀 | [Boolean] | 事件通常是否會出現(xiàn)冒泡 |
| cancelable 只讀 | [Boolean] | 事件是否可取消 |
| key 只讀 | [DOMString] (string) | 鍵更改時 |
| oldValue 只讀 | [DOMString] (string) | 正在更改鍵的舊值 |
| newValue 只讀 | [DOMString] (string) | 正在更改鍵的新值 |
| url 只讀 | DOMString | 鍵更改的文檔的地址 |
| storageArea 只讀 | [Storage] | 受影響的存儲對象 |
示例
例如,在一個標簽頁中修改LocalStorage的值:
localStorage.setItem('message', 'Hello from Tab 1!');
在另一個標簽頁中監(jiān)聽LocalStorage的變化:
window.onstorage = function(event) {
if (event.key === 'message') {
console.log(event.newValue); // 輸出:Hello from Tab 1!
}
};
window.open、window.postMessage
通過在一個標簽頁中使用window.open打開另一個標簽頁,并使用window.postMessage進行消息傳遞,可以實現(xiàn)跨標簽頁通信。
window.open()
open() open(url) open(url, target) open(url, target, windowFeatures)
url: 一個字符串,表示要加載的資源的 URL 或路徑。如果指定空字符串("")或省略此參數(shù),則會在目標瀏覽上下文中打開一個空白頁。target: 一個不含空格的字符串,用于指定加載資源的瀏覽上下文的名稱。windowFeatures: 一個字符串,包含以逗號分隔的窗口特性列表。
window.postMessage() 方法可以安全地實現(xiàn)跨源通信。通常,對于兩個不同頁面的腳本,只有當(dāng)執(zhí)行它們的頁面位于具有相同的協(xié)議(通常為 https),端口號(443 為 https 的默認值),以及主機 (兩個頁面的模數(shù) Document.domain設(shè)置為相同的值) 時,這兩個腳本才能相互通信。window.postMessage() 方法提供了一種受控機制來規(guī)避此限制,只要正確的使用,這種方法就很安全。
示例
例如,在一個標簽頁中發(fā)送消息:
const newTab = window.open('other.html');
newTab.postMessage('Hello from Tab 1!', '*');
在另一個標簽頁中接收消息:
window.addEventListener('message', function(event) {
console.log(event.data); // 輸出:Hello from Tab 1!
});
總結(jié)
- BroadCast Channel:使用Broadcast Channel API可以在不同的瀏覽器上下文之間進行消息廣播和接收。通過創(chuàng)建一個廣播頻道,并在不同的標簽頁中監(jiān)聽該頻道,可以實現(xiàn)跨標簽頁通信。
- Service Worker:Service Worker是一種在瀏覽器后臺運行的腳本,可以攔截和處理網(wǎng)絡(luò)請求。通過在Service Worker中監(jiān)聽和處理消息事件,可以實現(xiàn)跨標簽頁通信。
- LocalStorage window.onstorage 監(jiān)聽:通過在不同的標簽頁中監(jiān)聽LocalStorage的變化,可以實現(xiàn)跨標簽頁通信。當(dāng)一個標簽頁修改LocalStorage的值時,其他標簽頁可以通過監(jiān)聽storage事件來獲取最新值。
- window.open、window.postMessage:通過在一個標簽頁中使用window.open打開另一個標簽頁,并使用window.postMessage進行消息傳遞,可以實現(xiàn)跨標簽頁通信。這種方式適用于需要直接傳遞數(shù)據(jù)或消息的場景。
這些方案各有特點和適用場景。Broadcast Channel適用于需要實時廣播消息給所有打開的標簽頁的場景;Service Worker適用于需要在后臺進行數(shù)據(jù)處理或者發(fā)送消息給其他標簽頁的場景;LocalStorage window.onstorage監(jiān)聽適用于需要共享數(shù)據(jù)并及時獲取更新的場景;window.open、window.postMessage適用于需要直接傳遞數(shù)據(jù)或消息的場景。
到此這篇關(guān)于JavaScript常見的跨標簽頁通信方式總結(jié)的文章就介紹到這了,更多相關(guān)JavaScript跨標簽頁通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Javascript實現(xiàn)跨域后臺設(shè)置攔截的方法詳解
這篇文章主要給大家介紹了關(guān)于Javascript實現(xiàn)跨域后臺設(shè)置攔截的方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08
JS module的導(dǎo)出和導(dǎo)入的實現(xiàn)代碼
這篇文章主要介紹了JS module的導(dǎo)出和導(dǎo)入的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02
JavaScript如何使用dhtmlXTreeObject的loadJSONObject繪制目錄樹
這篇文章主要介紹了JavaScript如何使用dhtmlXTreeObject的loadJSONObject繪制目錄樹,需要引入dhtmlXTreeObject的css和js文件,這里還需要注意js的引用順序,本文給大家介紹的非常詳細,需要的的朋友參考下吧2023-11-11
uni-app封裝組件實現(xiàn)下方滑動彈出模態(tài)框效果
這篇文章主要介紹了uni-app封裝組件實現(xiàn)下方滑動彈出模態(tài)框效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-08-08
通過flv.js播放監(jiān)控示例深入探究直播流技術(shù)
本文記錄一下在使用 flv.js 播放監(jiān)控視頻時踩過的各種各樣的坑,雖然官網(wǎng)給的?Getting Started?只有短短幾行代碼,跑一個能播視頻的 demo 很容易,但是播放時各種各樣的異常會搞到你懷疑人生,下面我將自己踩過的坑,以及踩坑過程中補充的相關(guān)知識,詳細總結(jié)一下2023-10-10

