JavaScript中跨標(biāo)簽頁(yè)通信的常見(jiàn)方式
引言
跨標(biāo)簽頁(yè)通信是指在瀏覽器中的不同標(biāo)簽頁(yè)之間進(jìn)行數(shù)據(jù)傳遞和通信的過(guò)程。在傳統(tǒng)的Web開(kāi)發(fā)中,每個(gè)標(biāo)簽頁(yè)都是相互獨(dú)立的,無(wú)法直接共享數(shù)據(jù)。然而,有時(shí)候我們需要在不同的標(biāo)簽頁(yè)之間進(jìn)行數(shù)據(jù)共享或者實(shí)現(xiàn)一些協(xié)同操作,這就需要使用跨標(biāo)簽頁(yè)通信來(lái)實(shí)現(xiàn)。
常見(jiàn)的跨標(biāo)簽頁(yè)方案
- BroadCast Channel
- Service Worker
- LocalStorage window.onstorage 監(jiān)聽(tīng)
- window.open、window.postMessage
- Shared Worker 定時(shí)器輪詢( setInterval )
- IndexedDB 定時(shí)器輪詢( setInterval )
- cookie 定時(shí)器輪詢( setInterval )
- Websocket
前面4種方式可見(jiàn): 跨標(biāo)簽頁(yè)通信的8種方式(上)
本文介紹后面4種
Shared Worker
Shared Worker
是一種在多個(gè)瀏覽器標(biāo)簽頁(yè)之間共享的 JavaScript 線程。它可以用于實(shí)現(xiàn)跨標(biāo)簽頁(yè)的通信。
SharedWorker
接口代表一種特定類型的 worker,可以從幾個(gè)瀏覽上下文中訪問(wèn),例如幾個(gè)窗口、iframe 或其他 worker。它們實(shí)現(xiàn)一個(gè)不同于普通 worker 的接口,具有不同的全局作用域,
備注: 如果要使 SharedWorker 連接到多個(gè)不同的頁(yè)面,這些頁(yè)面必須是同源的(相同的協(xié)議、host 以及端口)。
兼容性
下面是一個(gè)使用 Shared Worker 進(jìn)行通信的示例:
在主頁(yè)面中:
// 創(chuàng)建一個(gè) Shared Worker const worker = new SharedWorker('worker.js'); // 監(jiān)聽(tīng)來(lái)自 Shared Worker 的消息 worker.port.onmessage = function(event) { console.log('Received message from worker:', event.data); }; // 向 Shared Worker 發(fā)送消息 worker.port.postMessage('Hello from main page!');
在 worker.js 文件中:
// 監(jiān)聽(tīng)來(lái)自主頁(yè)面的消息 self.onconnect = function(event) { const port = event.ports[0]; // 監(jiān)聽(tīng)來(lái)自主頁(yè)面的消息 port.onmessage = function(event) { console.log('Received message from main page:', event.data); // 向主頁(yè)面發(fā)送消息 port.postMessage('Hello from shared worker!'); }; };
IndexedDB
IndexedDB
是一種底層 API,用于在客戶端存儲(chǔ)大量的結(jié)構(gòu)化數(shù)據(jù)(也包括文件/二進(jìn)制大型對(duì)象(blobs))。該 API 使用索引實(shí)現(xiàn)對(duì)數(shù)據(jù)的高性能搜索。雖然 Web Storage 在存儲(chǔ)較少量的數(shù)據(jù)很有用,但對(duì)于存儲(chǔ)更大量的結(jié)構(gòu)化數(shù)據(jù)來(lái)說(shuō)力不從心。而 IndexedDB
提供了這種場(chǎng)景的解決方案。
IndexedDB
是一個(gè)事務(wù)型數(shù)據(jù)庫(kù)系統(tǒng),類似于基于 SQL 的 RDBMS。然而,不像 RDBMS 使用固定列表,IndexedDB
是一個(gè)基于 JavaScript 的面向?qū)ο髷?shù)據(jù)庫(kù)。IndexedDB 允許你存儲(chǔ)和檢索用鍵索引的對(duì)象;可以存儲(chǔ)結(jié)構(gòu)化克隆算法支持的任何對(duì)象。你只需要指定數(shù)據(jù)庫(kù)模式,打開(kāi)與數(shù)據(jù)庫(kù)的連接,然后檢索和更新一系列事務(wù)。
使用 IndexedDB 執(zhí)行的操作是異步執(zhí)行的,以免阻塞應(yīng)用程序。
IndexedDB
是瀏覽器提供的一種本地?cái)?shù)據(jù)庫(kù),可以用于在多個(gè)標(biāo)簽頁(yè)之間共享數(shù)據(jù)??梢允褂?setInterval 定時(shí)輪詢 IndexedDB 來(lái)實(shí)現(xiàn)跨標(biāo)簽頁(yè)通信。下面是一個(gè)示例:
在發(fā)送消息的標(biāo)簽頁(yè)中:
// 打開(kāi)或創(chuàng)建 IndexedDB 數(shù)據(jù)庫(kù) const request = indexedDB.open('messageDatabase', 1); request.onupgradeneeded = function(event) { const db = event.target.result; // 創(chuàng)建一個(gè)對(duì)象存儲(chǔ)空間用于存儲(chǔ)消息 db.createObjectStore('messages', { keyPath: 'id', autoIncrement: true }); }; request.onsuccess = function(event) { const db = event.target.result; // 向數(shù)據(jù)庫(kù)中添加一條新消息 const transaction = db.transaction(['messages'], 'readwrite'); const objectStore = transaction.objectStore('messages'); const message = { content: 'Hello from sender!' }; objectStore.add(message); transaction.oncomplete = function() { console.log('Message sent successfully!'); // 關(guān)閉數(shù)據(jù)庫(kù)連接 db.close(); }; }; request.onerror = function(event) { console.error('Error opening database:', event.target.error); };
在接收消息的標(biāo)簽頁(yè)中:
// 打開(kāi)或創(chuàng)建 IndexedDB 數(shù)據(jù)庫(kù) const request = indexedDB.open('messageDatabase', 1); request.onsuccess = function(event) { const db = event.target.result; // 創(chuàng)建一個(gè)定時(shí)器,每隔一段時(shí)間輪詢數(shù)據(jù)庫(kù)中的消息 setInterval(function() { // 創(chuàng)建一個(gè)事務(wù) const transaction = db.transaction(['messages'], 'readwrite'); const objectStore = transaction.objectStore('messages'); // 獲取存儲(chǔ)在對(duì)象存儲(chǔ)中的所有消息 const request = objectStore.getAll(); request.onsuccess = function(event) { const messages = event.target.result; // 處理消息 messages.forEach(function(message) { console.log('Received message:', message.content); // 在處理完消息后,刪除該消息 objectStore.delete(message.id); }); // 關(guān)閉事務(wù) transaction.oncomplete = function() { console.log('Messages processed successfully!'); }; }; request.onerror = function(event) { console.error('Error retrieving messages:', event.target.error); // 關(guān)閉事務(wù) transaction.abort(); }; }, 1000); }; request.onerror = function(event) { console.error('Error opening database:', event.target.error); };
在上述示例中,我們創(chuàng)建了一個(gè)名為 "messageDatabase" 的 IndexedDB 數(shù)據(jù)庫(kù),并在其中創(chuàng)建了一個(gè)名為 "messages" 的對(duì)象存儲(chǔ)空間用于存儲(chǔ)消息。在發(fā)送消息的標(biāo)簽頁(yè)中,我們向數(shù)據(jù)庫(kù)中添加一條新消息。而在接收消息的標(biāo)簽頁(yè)中,我們創(chuàng)建了一個(gè)定時(shí)器,每隔一段時(shí)間輪詢數(shù)據(jù)庫(kù)中的消息,并處理這些消息。處理完消息后,我們將其從數(shù)據(jù)庫(kù)中刪除。
請(qǐng)注意,在實(shí)際應(yīng)用中,您可能需要更復(fù)雜的邏輯來(lái)處理跨標(biāo)簽頁(yè)通信,并確保數(shù)據(jù)同步和一致性。此示例僅提供了一個(gè)基本的框架來(lái)演示如何使用 IndexedDB 實(shí)現(xiàn)跨標(biāo)簽頁(yè)通信。
cookie
Cookie 是一種在瀏覽器和服務(wù)器之間傳遞的小型文本文件,可以用于在多個(gè)標(biāo)簽頁(yè)之間共享數(shù)據(jù)??梢允褂?setInterval 定時(shí)輪詢 Cookie 來(lái)實(shí)現(xiàn)跨標(biāo)簽頁(yè)通信。下面是一個(gè)示例:
在發(fā)送消息的標(biāo)簽頁(yè)中:
// 設(shè)置一個(gè) Cookie,將消息存儲(chǔ)在 Cookie 中 document.cookie = 'message=Hello from sender!';
在接收消息的標(biāo)簽頁(yè)中:
// 創(chuàng)建一個(gè)定時(shí)器,每隔一段時(shí)間輪詢 Cookie 中的數(shù)據(jù) setInterval(function () { // 獲取存儲(chǔ)在 Cookie 中的消息 const cookies = document.cookie.split(';') let message = '' for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim() if (cookie.startsWith('message=')) { message = cookie.substring('message='.length) break } } // 處理消息 if (message) { console.log('Received message:', decodeURIComponent(message)) // 清除 Cookie document.cookie = 'message=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;' } }, 1000)
在上述示例中,我們?cè)诎l(fā)送消息的標(biāo)簽頁(yè)中設(shè)置了一個(gè)名為 "message" 的 Cookie,并將消息存儲(chǔ)在其中。而在接收消息的標(biāo)簽頁(yè)中,我們創(chuàng)建了一個(gè)定時(shí)器,每隔一段時(shí)間輪詢 Cookie 中的數(shù)據(jù)。通過(guò)解析和處理 Cookie,我們可以獲取到存儲(chǔ)的消息,并進(jìn)行相應(yīng)的處理。處理完消息后,我們清除了該 Cookie。 請(qǐng)注意,在使用 Cookie 進(jìn)行跨標(biāo)簽頁(yè)通信時(shí),需要注意以下幾點(diǎn):
- 跨域名通信:Cookie 默認(rèn)只能在同一域名下共享。如果需要在不同域名下進(jìn)行跨標(biāo)簽頁(yè)通信,需要設(shè)置合適的域名和路徑。
- Cookie 大小限制:Cookie 的大小有限制,通常為幾 KB。如果消息較大,可能需要拆分成多個(gè) Cookie 進(jìn)行存儲(chǔ)。
- 安全性考慮:Cookie 中的數(shù)據(jù)可以被用戶和其他腳本訪問(wèn)和修改。因此,不適合存儲(chǔ)敏感信息。 以上示例提供了一個(gè)基本的框架來(lái)演示如何使用 Cookie 實(shí)現(xiàn)跨標(biāo)簽頁(yè)通信。在實(shí)際應(yīng)用中,您可能需要更復(fù)雜的邏輯來(lái)處理跨標(biāo)簽頁(yè)通信,并確保數(shù)據(jù)同步和一致性。
websocket
Websocket 是一種在瀏覽器和服務(wù)器之間進(jìn)行全雙工通信的協(xié)議,可以用于實(shí)現(xiàn)實(shí)時(shí)的跨標(biāo)簽頁(yè)通信。下面是一個(gè)使用 Websocket 進(jìn)行通信的示例:
在發(fā)送消息的標(biāo)簽頁(yè)中:
// 創(chuàng)建一個(gè) WebSocket 連接 const socket = new WebSocket('ws://example.com'); // 監(jiān)聽(tīng)連接成功的事件 socket.onopen = function() { // 發(fā)送消息到服務(wù)器 socket.send('Hello from sender!'); };
在接收消息的標(biāo)簽頁(yè)中:
// 創(chuàng)建一個(gè) WebSocket 連接 const socket = new WebSocket('ws://example.com'); // 監(jiān)聽(tīng)來(lái)自服務(wù)器的消息 socket.onmessage = function(event) { console.log('Received message:', event.data); };
在服務(wù)器端:
// 創(chuàng)建一個(gè) WebSocket 服務(wù)器 const WebSocketServer = require('ws').Server const wss = new WebSocketServer({ port: 8080 }) // 監(jiān)聽(tīng)來(lái)自客戶端的連接 wss.on('connection', function (socket) { // 監(jiān)聽(tīng)來(lái)自客戶端的消息 socket.on('message', function (message) { console.log('Received message:', message) // 向所有客戶端發(fā)送消息 wss.clients.forEach(function (client) { client.send(message) }) }) })
在上述示例中,我們?cè)诎l(fā)送消息的標(biāo)簽頁(yè)中創(chuàng)建了一個(gè) WebSocket 連接,并在連接成功后發(fā)送一條消息到服務(wù)器。而在接收消息的標(biāo)簽頁(yè)中,我們也創(chuàng)建了一個(gè) WebSocket 連接,并監(jiān)聽(tīng)來(lái)自服務(wù)器的消息。當(dāng)服務(wù)器收到來(lái)自任何客戶端的消息時(shí),它會(huì)將該消息廣播給所有連接的客戶端。
總結(jié)
這些通信方式各有優(yōu)劣,選擇適合的方式取決于具體的需求和場(chǎng)景。Shared Worker 和 Websocket 提供了實(shí)時(shí)性和雙向通信的能力,適用于需要實(shí)時(shí)更新和交互的應(yīng)用。IndexedDB 和 Cookie 則適用于需要存儲(chǔ)和同步數(shù)據(jù)的場(chǎng)景,但相對(duì)于實(shí)時(shí)性較差。根據(jù)具體需求,可以選擇合適的通信方式來(lái)實(shí)現(xiàn)跨標(biāo)簽頁(yè)的通信。
到此這篇關(guān)于JavaScript中跨標(biāo)簽頁(yè)通信的常見(jiàn)方式的文章就介紹到這了,更多相關(guān)JavaScript跨標(biāo)簽頁(yè)通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JavaScript中不同標(biāo)簽頁(yè)間通信的常見(jiàn)方式小結(jié)
- JavaScript中瀏覽器多標(biāo)簽頁(yè)通信的8種方案盤點(diǎn)
- JavaScript實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)通信方式詳解
- JavaScript實(shí)現(xiàn)瀏覽器內(nèi)多個(gè)標(biāo)簽頁(yè)之間通信
- JavaScript使用Broadcast?Channel實(shí)現(xiàn)前端跨標(biāo)簽頁(yè)通信
- JavaScript中實(shí)現(xiàn)跨標(biāo)簽頁(yè)通信的方法詳解
- JavaScript常見(jiàn)的跨標(biāo)簽頁(yè)通信方式總結(jié)
- JavaScript實(shí)現(xiàn)瀏覽器不同標(biāo)簽頁(yè)通信的原理與實(shí)踐
相關(guān)文章
js Canvas實(shí)現(xiàn)的日歷時(shí)鐘案例分享
本文主要分享了js實(shí)現(xiàn)的日歷時(shí)鐘案例,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2016-12-12JavaScript 實(shí)現(xiàn)打印,打印預(yù)覽,打印設(shè)置
這篇文章主要介紹了JavaScript 實(shí)現(xiàn)打印,打印預(yù)覽,打印設(shè)置的方法及示例分享,需要的朋友可以參考下2014-12-12JavaScript Memoization 讓函數(shù)也有記憶功能
函數(shù)可以用對(duì)象去記住先前操作的結(jié)果,從而能避免無(wú)謂的運(yùn)算,這種優(yōu)化被稱為記憶(Memoization)。JavaScript 的對(duì)象和數(shù)組要實(shí)現(xiàn)這種優(yōu)化是非常方便的。2011-10-10簡(jiǎn)單使用webpack打包文件的實(shí)現(xiàn)
這篇文章主要介紹了簡(jiǎn)單使用webpack打包文件的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10