浏览器跨标签页通信的8种常见的方式

一:什么是浏览器跨标签页通信?

浏览器跨标签页通信是指在同一个浏览器窗口中的多个标签页之间进行数据交流和信息传递的过程。通常情况下,每个标签页都是一个独立的浏览器上下文,它们之间是相互隔离的,无法直接访问对方的数据或进行通信。

跨标签页通信的目的是允许这些相互隔离的标签页之间进行信息共享和交互。通过跨标签页通信,可以实现数据的共享、状态的同步、消息的传递等功能。

例如,在一个标签页中进行了某个操作,希望其他标签页能够及时获得相关的变化和通知,就需要使用跨标签页通信机制来实现这种交互。

二:浏览器跨标签页通信主要用在哪些需求里面

浏览器跨标签页通信主要用于以下几种需求:

1:数据共享:当多个标签页需要访问和共享相同的数据时,跨标签页通信可以用于在这些标签页之间传递数据,确保它们保持同步。

2:状态同步:在一些应用中,可能会有多个标签页用于展示相同的应用状态或会话状态。通过跨标签页通信,可以实现状态的同步,使得在一个标签页中的操作能够即时反映到其他标签页上。

3:消息通知:跨标签页通信可以用于实现在一个标签页中发送消息,然后其他标签页接收并展示这些消息的功能。

4:共享资源:在某些场景下,可能需要在多个标签页之间共享某些资源,如网络连接、音频/视频播放器等。

5:多窗口管理:对于一些具有多个窗口的应用,跨标签页通信可以用于实现窗口之间的联动和数据同步。

三:浏览器跨标签页通信可以通过以下几种常见方式实现:

1:LocalStorage 或 SessionStorage:使用 Web 存储机制(LocalStorage 或 SessionStorage)可以在不同标签页之间共享数据。一个标签页可以将数据存储在 LocalStorage 或 SessionStorage 中,其他标签页可以监听存储事件来获取更新的数据。

使用 LocalStorage 或 SessionStorage 实现跨标签页通信的一个简单案例代码:

// 在一个标签页中写入数据到 LocalStorage 或 SessionStorage
localStorage.setItem('sharedData', 'Hello from Tab 1');
// 或者 sessionStorage.setItem('sharedData', 'Hello from Tab 1');

// 在其他标签页中监听存储事件,并获取更新的数据
window.addEventListener('storage', function(event) {
  if (event.key === 'sharedData') {
    const newData = event.newValue;
    console.log('Received updated data:', newData);
  }
});

// 在另一个标签页中更新数据
localStorage.setItem('sharedData', 'Hello from Tab 2');
// 或者 sessionStorage.setItem('sharedData', 'Hello from Tab 2');

在这个例子中,首先在一个标签页中通过localStorage.setItem()sessionStorage.setItem()方法将数据写入到LocalStorageSessionStorage中。然后,在其他标签页中通过监听 storage 事件来捕获存储事件,并判断事件的 key 是否为我们共享的数据 sharedData,如果是,则获取更新的数据 newValue 并进行处理。

接下来,在另一个标签页中通过 localStorage.setItem()sessionStorage.setItem()方法更新数据。

2:Broadcast Channel API:Broadcast Channel API 允许不同标签页之间通过共享的通道进行消息广播和接收。一个标签页可以通过通道发送消息,其他订阅了相同通道的标签页可以接收到这些消息。

使用 Broadcast Channel API 实现跨标签页通信的一个简单案例代码:

在发送消息的标签页中:

// 创建一个广播通道
const channel = new BroadcastChannel('myChannel');

// 发送消息
channel.postMessage('Hello from Tab 1');

在接收消息的标签页中:

// 创建一个广播通道
const channel = new BroadcastChannel('myChannel');

// 监听消息事件
channel.onmessage = function(event) {
  const message = event.data;
  console.log('Received message:', message);
};

首先在发送消息的标签页中创建一个Broadcast Channel,并指定一个唯一的通道名称(这里使用 'myChannel')。通过 channel.postMessage()方法发送消息到该通道。

在接收消息的标签页中,同样创建一个具有相同通道名称的 Broadcast Channel。然后,通过为 channel.onmessage 赋值一个函数,来监听消息事件。当接收到消息时,事件对象 event 中的 data 属性将包含发送的消息内容,我们可以在监听函数中获取并处理该消息。

3:SharedWorker:SharedWorker 是一种在多个标签页之间共享的后台线程。标签页可以通过 SharedWorker 进行通信,发送消息和接收消息。这种方式需要使用 JavaScript 的 Worker API。

使用 SharedWorker 实现跨标签页通信的一个简单案例代码:

在发送消息的标签页中:

// 创建一个 SharedWorker
const worker = new SharedWorker('worker.js');

// 发送消息
worker.port.postMessage('Hello from Tab 1');

在共享的 Worker 脚本文件 worker.js 中:

// 监听连接事件
self.onconnect = function(event) {
  const port = event.ports[0];
  
  // 监听消息事件
  port.onmessage = function(event) {
    const message = event.data;
    console.log('Received message:', message);
  };
  
  // 发送消息
  port.postMessage('Hello from Worker');
};

在发送消息的标签页中创建一个 SharedWorker,并指定共享的 Worker 脚本文件路径为 'worker.js'。然后,通过 worker.port.postMessage()方法发送消息到 SharedWorker。

在共享的 Worker 脚本文件 worker.js 中,通过监听 self.onconnect 事件来捕获连接事件,并获取与标签页之间的通信端口 port。然后,通过为 port.onmessage 赋值一个函数,来监听消息事件。当接收到消息时,事件对象 event 中的 data 属性将包含发送的消息内容,我们可以在监听函数中获取并处理该消息。

4:Service Worker:Service Worker 是一种独立于网页的脚本,可以在后台运行,提供离线缓存和消息传递等功能。标签页可以通过 Service Worker 进行通信,发送消息和接收消息。

5:Window.postMessage():Window.postMessage() 方法允许在不同的窗口或标签页之间安全地传递消息。通过调用 postMessage() 方法并指定目标窗口的 origin,可以将消息发送到其他标签页,并通过监听 message 事件来接收消息。

使用 window.postMessage() 实现跨标签页通信的一个简单案例代码:

在发送消息的标签页中:

// 监听消息事件
window.addEventListener('message', function(event) {
  // 确保消息来自预期的源
  if (event.origin !== 'http://example.com') {
    return;
  }

  const message = event.data;
  console.log('Received message:', message);
});

// 发送消息到其他标签页
const targetWindow = window.open('http://example.com/otherpage', '_blank');
targetWindow.postMessage('Hello from Tab 1', 'http://example.com');

在接收消息的标签页中

// 监听消息事件
window.addEventListener('message', function(event) {
  // 确保消息来自预期的源
  if (event.origin !== 'http://example.com') {
    return;
  }

  const message = event.data;
  console.log('Received message:', message);

  // 回复消息
  event.source.postMessage('Hello from Other Tab', event.origin);
});

在发送消息的标签页中通过使用 window.addEventListener('message', ...) 监听消息事件。在事件处理函数中,可以用 event.origin 来验证消息的来源是否符合预期。然后,可以用 event.data 获取到发送的消息内容,并进行相应的操作。

在发送消息的标签页中,用 window.open() 打开了一个新的标签页(http://example.com/otherpage),然后通用 targetWindow.postMessage() 向该标签页发送消息。在这里,我们指定了消息的目标窗口和预期的来源(即目标标签页的 URL)。

在接收消息的标签页中,同样通过 window.addEventListener('message', ...) 监听消息事件,并在事件处理函数中进行相应的操作。

6:使用 Cookies:可以将需要共享的数据存储在 Cookies 中,并在不同的标签页之间读取和更新这些 Cookies。当一个标签页更新数据时,将数据写入到 Cookies 中,其他标签页可以通过监听 Cookies 变化事件或定时读取 Cookies 来获取最新的数据。

使用 Cookies 进行通信是一种简单的方法,但它主要用于在客户端和服务器之间传递数据,而不是直接实现跨标签页通信。Cookies 会自动在客户端和服务器之间进行传递,因此可以在不同的标签页之间共享数据。

下面是一个使用 Cookies 在标签页之间传递数据的简单案例代码:

在发送消息的标签页中:

// 设置 Cookie
document.cookie = 'sharedData=Hello from Tab 1';

在接收消息的标签页中:

// 获取 Cookie 值
const cookies = document.cookie;
const cookieArr = cookies.split(';');

let sharedData = null;
for (let i = 0; i < cookieArr.length; i++) {
  const cookie = cookieArr[i].trim();
  if (cookie.startsWith('sharedData=')) {
    sharedData = cookie.substring('sharedData='.length, cookie.length);
    break;
  }
}

console.log('Received message:', sharedData);

7:使用 IndexedDB:IndexedDB 是浏览器提供的一个客户端数据库,可以在不同的标签页之间存储和读取数据。一个标签页可以将数据写入 IndexedDB,其他标签页可以监听 IndexedDB 的变化事件或定时从 IndexedDB 中读取数据来实现数据的共享和状态的同步。

下面是一个使用IndexedDB进行通信的简单案例代码:

// 打开或创建IndexedDB数据库
const request = indexedDB.open('myDatabase', 1);

// 成功打开数据库
request.onsuccess = function(event) {
  const db = event.target.result;

  // 创建一个对象存储空间(类似表)
  const objectStore = db.createObjectStore('messages', { keyPath: 'id', autoIncrement: true });

  // 添加一条消息到对象存储空间
  const message = { text: 'Hello, World!' };
  const addRequest = objectStore.add(message);

  addRequest.onsuccess = function(event) {
    console.log('消息已添加到IndexedDB');
  };

  addRequest.onerror = function(event) {
    console.error('添加消息到IndexedDB时发生错误');
  };

  // 从对象存储空间获取所有消息
  const getAllRequest = objectStore.getAll();

  getAllRequest.onsuccess = function(event) {
    const messages = event.target.result;
    console.log('所有消息:', messages);
  };

  getAllRequest.onerror = function(event) {
    console.error('获取消息时发生错误');
  };
};

// 打开或创建数据库时发生错误
request.onerror = function(event) {
  console.error('打开/创建数据库时发生错误');
};

// 数据库版本变更
request.onupgradeneeded = function(event) {
  const db = event.target.result;

  // 创建一个对象存储空间
  const objectStore = db.createObjectStore('messages', { keyPath: 'id', autoIncrement: true });

  console.log('数据库版本已更新');
};

8:使用服务器端存储:将需要共享的数据存储在服务器端,标签页之间通过与服务器进行通信来获取和更新数据。可以使用 AJAX、WebSocket 或其他网络通信技术来实现与服务器的数据交互。

注意:使用服务器端存储的方法可能需要进行网络请求,可能会涉及到延迟和带宽消耗。

而使用本地存储(如LocalStorage、SessionStorage)或客户端数据库(如IndexedDB)的方法更加直接和快速,适用于较小规模的数据共享和状态同步。

这些是常见的浏览器跨标签页通信的方式。具体选择哪种方式取决于你的需求和使用场景。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容