成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

六種瀏覽器跨窗口通信方案 - 從實際案例出發

系統 瀏覽器
各種方式都可以實現通知列表頁去做刷新動作,不過更推薦使用 window.opener? 或 BroadcastChannel 來實現,這兩種方式相對使用簡單并且很符合這個業務場景。

瀏覽器跨窗口通信,聽上去挺有技術感的,但實現起來方案倒是挺多的。本文將從一個實際的業務開發場景,帶你了解如何實現瀏覽器跨窗口通信。

業務場景

一個常規的業務列表頁,頁面中提供了一個新增功能,由于新增功能的表單項內容比較多,所以交互上使用新開一個窗口來完成。這時問題來了,在新增完成后,如何通知列表頁面刷新列表數據,以便展示出剛才新增的那一條數據。

圖片圖片

各位可以先自己在心中簡單想想,如果讓你實現這個功能,你會使用什么方案。

解決方案

window.opener

window.opener 代表的是打開當前窗口的那個窗口的引用,例如:在 window A 中打開了 window B,B.opener 返回 A。

有了這個引用關系,我們就可以實現跨窗口通信:

圖片圖片

  1. 列表頁設置刷新列表方法 window.refreshList = () => {}
  2. 列表頁通過 window.open 或者 <a href="newUrl" target="_blank" rel="opener">新增</a> 打開新增功能頁面。
  3. 用戶完成新增表單填寫并提交,通過調用 window.opener.refreshList 方法來刷新列表頁面數據,并關閉當前頁。

有人可能注意到了,在 a 標簽中我們使用到了 rel="opener" 屬性,為什么要設置這個屬性呢?

rel 屬性定義了所鏈接的資源與當前文檔的關系,常見的屬性值有:

  • opener: 打開的新頁面 window.opener 會指向前一個頁面的 window。
  • noopener: 和 opener 相對應, window.opener 為空。
  • noreferrer:打開新頁面時請求頭不會包含 Referer,比如你未設置 noreferrer 的情況下,從 antd 打開百度,百度頁面請求頭就有 Referer: https://ant.design/
  • nofollow: 主要用于 SEO,告訴搜索引擎忽略該鏈接。

主要關注 opener 和 noopener 屬性,a 標簽默認情況下 rel=noopener,這代表打開的新增頁面的 window.opener 對象會為空,所以需要設置 rel=opener。

那么又有一個問題,為什么 a 標簽默認是 rel=noopener, 因為 opener 存在安全漏洞,比如你以 opener 的方式打開了一個未知的新頁面,這個新頁面可以通過 window.opener.location.href = 'fake.com' 重定向你的頁面。

而 window.open 默認情況下 rel=opener,故打開的新頁面可以拿到 window.opener 對象,不過要是打開第三方未知網站,建議設置為 noopener, 比如 window.open('https://baidu.com', 'title', 'noopener,noreferrer')。

BroadcastChannel

BroadcastChannel API 顧名思義,為“廣播頻道”,適用于在同一域名下的多個窗口、標簽頁或 iframe 之間進行實時消息廣播。它的使用也非常簡單,我們也看下如何通過它來實現上面的業務場景。

列表頁創建一個 BroadcastChannel 實例來監聽消息:

// 創建 BroadcastChannel 實例
const channel = new BroadcastChannel('myChannel');

// 監聽廣播通道的消息
channel.addEventListener('message', (event) => {
  console.log('接收:', event.data); // { action: 'refresh' }
})

新增功能頁面同樣創建一個 BroadcastChannel 實例,頻道名稱需要和列表頁一致:

// 創建 BroadcastChannel 實例
const channel = new BroadcastChannel('myChannel');
// 向廣播通道發送消息
channel.postMessage({ action: 'refresh' });
// 關閉頻道
channel.close()

可以看到 BroadcastChannel 的使用很簡單,雙方創建同名頻道的 BroadcastChannel 實例,然后一方監聽 message 事件,一方使用 postMessage 廣播內容。

postMessage

對于 postMessage,我們最常用的方式應該就是當前頁面和 iframe 的跨域消息通信了,其實它也能完成跨窗口通信,核心就是能拿到新窗口的 window 對象,這個在 window.opener 方案中我們就知道通過設置 rel="opener" 就可以辦到。

列表頁打開新窗口,并監聽 message 事件:

<a href="./add.html" target="_blank" rel="opener">新增</a>
<script>
  // 不同與 BroadcastChannel,這邊是監聽 window 上的 message 事件
  window.addEventListener("message", receiveMessage);
  function receiveMessage(event) {
    console.log('接收:', event.data); // { action: 'refresh' }
  }
</script>

新增功能頁面使用 window.opener.postMessage 發送消息:

window.opener?.postMessage({ action: 'refresh' }, '*');

至此我們已經完成了上面的業務需求,postMessage 的優勢在于可以跨域。

MessageChannel

MessageChannel API 允許我們創建一個新的消息通道,并通過它的兩個 MessagePort 實例屬性發送數據,同時它也可以跨域通信。

不同于 BroadcastChannel 的廣播,MessageChannel 只提供雙向通信通道,不過它既可以像 postMessage 一樣用于 iframe 通信,也可以用于 Web Worker 之間進行通信。

圖片圖片

要用 MessageChannel 實現跨窗口通信,方式有點類似 postMessage, 打開新頁面時需要設置 rel="opener"。

列表頁初始化 MessageChannel 實例,并在 port1 上監聽 message 事件:

// 創建 MessageChannel 實例
window.messageChannel = new MessageChannel();
const port1 = window.messageChannel.port1;
// port1 監聽 message 事件
port1.onmessage = function(event) {
  console.log('接收:', event.data); // { action: 'refresh' }
};

新增功能頁面使用 window.opener.messageChannel 拿到列表的 MessageChannel 實例,并使用 port2 的 postMessage 方法往 port1 通道上發送消息:

// 獲取 MessageChannel 實例
const messageChannel = window.opener.messageChannel;
const port2 = messageChannel.port2;
// 往 port1 發送消息
port2.postMessage({ action: 'refresh' });

需要注意的是 MessagePort 對象如果使用 addEventListener 監聽 message 事件,就需要調用下 port.start() 方法,使用 onmessage 則可以不需要。

storage 事件

當 localStorage 或 sessionStorage 被修改時,將觸發 storage 事件,利用這個機制,我們也可以完成跨窗口通信。同時因為用的是 localStorage 或 sessionStorage 方式,所以頁面必須是同一域名下。

值得注意的是,sessionStorage 并不能滿足上面的業務需求,sessionStorage 要想觸發 storage 事件,必須在同一窗口,也就是一般只在當前頁和其加載的同域名 iframe 下使用。還有一點就是當前頁的 setItem 不會觸發當前頁的 storage 事件,只會觸發其他窗口的。

列表頁監聽 storage 事件,判斷是否是對應 key 值發生變化:

window.addEventListener("storage", () => {
  console.log('發生變化的值:', event.key); 
  if (event.key === 'refresh') {
     // 刷新列表
  }
});

新增功能頁面使用 localStorage 的 setItem 來觸發列表的 storage 事件:

window.localStorage.setItem('fresh', Date.now())

SharedWorker

SharedWorker 是 Web Workers API 的一種擴展,它允許在多個瀏覽器上下文中(例如多個頁面或多個 iframe )共享一個 Worker。ShareWorker 遵守同源策略,也就是必須在同一域名下使用 SharedWorker。

先寫個 worker.js 腳本:

const ports = [];

onconnect = function (e) {
  const port = e.ports[0];
  ports.push(port);
  port.onmessage = function (e) {
    console.log("worker接收到的消息:", e.data);
    ports.forEach((p) => {
      p.postMessage(e.data);
    });
  };
};

列表頁創建 ShareWorker 實例,然后監聽 message 事件:

const sharedWorker = new SharedWorker('./worker.js', 'test');
const port = sharedWorker.port;
port.onmessage = function (event) {
  console.log('接收:', event.data); // { action: 'refresh' }
};

新增功能頁面使用 postMessage 發送消息給 worker,worker 在發送給各個主線程:

const sharedWorker = new SharedWorker('./worker.js', 'test');
const port = sharedWorker.port;
port.postMessage({ action: 'refresh' });

這樣我們就完成了上述的業務需求。

總結

上述的各種方式都可以實現通知列表頁去做刷新動作,不過更推薦使用 window.opener 或 BroadcastChannel 來實現,這兩種方式相對使用簡單并且很符合這個業務場景。

對于其他需要跨窗口通信的場景,可以根據各個 API 的能力特點來選擇使用哪個。

責任編輯:武曉燕 來源: 栗子前端
相關推薦

2018-04-11 10:51:25

多線程進程主線程

2022-04-07 18:49:56

項目場景數據庫

2019-01-17 10:58:52

JS異步編程前端

2009-04-17 22:25:16

多核四核CPU

2012-01-04 16:14:17

2025-05-06 00:00:05

MySQLES協同

2025-05-19 00:02:00

數據脫敏加密算法數據庫

2019-05-15 08:00:00

vue組件間通信前端

2019-12-03 12:16:36

物聯網ZigBee藍牙低功耗

2022-05-24 10:43:02

延時消息分布式MQ

2009-03-12 10:11:00

綜合布線規劃網絡布局

2013-12-06 14:57:24

瀏覽器

2019-10-12 01:10:09

物聯網無線技術IOT

2010-05-31 10:11:02

2025-03-17 08:07:11

2010-09-15 09:12:03

JavaScript瀏覽器兼容

2018-01-12 10:25:48

Nginx信號集master

2025-05-29 03:00:00

2009-02-11 09:46:00

ASON網絡演進

2011-12-08 15:40:16

UC瀏覽器
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本一区高清 | 伊人久久在线观看 | 亚洲视频免费在线 | 亚洲综合国产精品 | 波多野结衣电影一区 | 日韩一 | 美女爽到呻吟久久久久 | 欧美一级片免费看 | 久久成人av | 国产精品久久久久久久久久久免费看 | 在线免费观看日本 | 精品国产精品 | 欧美视频日韩 | 久久99精品国产自在现线小黄鸭 | 亚洲精品久久久久久久久久久久久 | 丁香婷婷综合激情五月色 | 一区二区三区四区在线 | 亚洲精品粉嫩美女一区 | 精品国产免费人成在线观看 | 精品1区2区3区 | 久久久久久久国产精品影院 | 国产区在线免费观看 | 在线播放一区二区三区 | 国产美女黄色片 | 久久精品国产一区二区电影 | 久久这里只有精品首页 | 精品美女久久久 | 性一交一乱一透一a级 | 国产一区二区三区四区五区加勒比 | 色综合久久88色综合天天 | av日韩在线播放 | av资源中文在线 | 成人激情视频免费在线观看 | 日韩伦理电影免费在线观看 | 久久综合九九 | 99久久精品一区二区成人 | 曰批视频在线观看 | 欧美成人a | 欧美精品在线免费观看 | 亚洲欧美中文日韩在线v日本 | 亚洲欧洲一区 |