1 postMessage 核心
postMessage
?是現代瀏覽器提供的跨域通信標準 API,允許不同源的窗口(如主頁面與 iframe、彈出窗口、Web Worker)安全交換數據。相比其他跨域方案,它的核心優勢在于:
-
雙向通信能力:支持消息的發送與接收,形成完整的通信閉環
-
安全可控性:通過
targetOrigin
和event.origin
嚴格校驗消息源,防止惡意攻擊 -
跨場景兼容性:適用于 iframe 嵌套、多標簽頁同步、Web Worker 等多種場景
-
數據靈活性:支持對象、數組、Blob 等復雜數據類型(基于結構化克隆算法)
1.1 核心 API
1.1.1 發送消息:安全傳遞數據到目標窗口
otherWindow.postMessage(message, targetOrigin);
參數 | 描述 |
---|---|
| 目標窗口引用,可通過以下方式獲取: |
| 要發送的數據,支持?結構化克隆算法(可包含對象、數組、Blob 等,但需避免函數、DOM 節點)。 |
| 嚴格限制接收方的源(格式: |
示例:父窗口向 iframe 發送配置數據
// 父窗口代碼
const iframe = document.getElementById('myIframe');
iframe.contentWindow.postMessage({ type: 'init', config: { theme: 'dark' } },'https://child-domain.com' // 嚴格指定iframe的域名
);
1.1.2 接收消息:監聽并處理跨域數據
window.addEventListener('message', (event) => {const { data, origin, source } = event;// 1. 校驗消息來源(安全關鍵)if (origin !== 'https://trusted.com') {console.warn('未知來源的消息:', origin);return;}// 2. 處理消息數據(根據約定的格式)switch (data.type) {case 'login':console.log('用戶登錄信息:', data.user);break;case 'logout':// 執行登出邏輯break;}// 3. 可選:回復消息(通過source窗口)source.postMessage({ status: 'received' }, origin);
});
屬性 | 描述 |
---|---|
event.data | 發送方傳遞的數據(類型與發送時一致)。 |
event.origin | 發送方的源(如?https://sender.com ),用于安全校驗。 |
event.source | 發送方的窗口引用,可用于回復消息(調用?source.postMessage() )。 |
2 實戰案例
2.1 服務端A(servera.js)
// 引入Express框架,這是一個基于Node.js的快速、靈活的Web應用框架
const express = require('express');
// 創建一個Express應用實例,用于處理HTTP請求和響應
const app = express();
// 配置Express應用使用靜態文件中間件,指定從'public'文件夾中提供靜態資源(如HTML、CSS、圖片等)
app.use(express.static('public'));
// 定義應用監聽的端口號,3000是前端開發中常用的非特權端口
const port = 3000;
// 啟動服務器并監聽指定端口,當服務器成功啟動后執行回調函數
app.listen(port, () => {// 在控制臺輸出服務器運行的地址信息,方便開發者確認服務啟動狀態console.log(`Server is running on http://localhost:${port}`);
});
2.2 靜態頁面A(a.html)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>a</title>
</head>
<body><!-- 插入id為"b-iframe"的iframe元素,指向http://localhost:4000/b.htmlonload事件在iframe資源加載完成后觸發handleIframeLoad函數 --><iframe id="b-iframe" src="http://localhost:4000/b.html" onload="handleIframeLoad()"></iframe><script>// 定義目標源,與iframe的源保持一致,用于postMessage安全校驗const targetOrigin = 'http://localhost:4000';// iframe加載完成后的處理函數function handleIframeLoad() {// 通過contentWindow獲取iframe的window對象,用于跨窗口通信let bWindow = document.getElementById('b-iframe').contentWindow;// 向iframe發送消息,第二個參數指定目標源防止惡意窗口接收bWindow.postMessage('hello', targetOrigin);}// 監聽當前窗口的message事件,接收來自其他窗口的跨域消息window.addEventListener('message', function(event) {// 輸出接收到的消息內容(包含event.data、event.origin等安全信息)console.log('Received message: ', event.data);}, false);</script>
</body>
</html>
2.3 服務端B(serverb.js)
// 引入Express框架(基于Node.js的Web應用開發框架,提供路由、中間件等功能)
const express = require('express');
// 創建Express應用實例(核心對象,用于處理HTTP請求和響應)
const app = express();
// 配置靜態資源中間件(指定從'public'文件夾中讀取HTML、CSS、圖片等靜態文件)
app.use(express.static('public'));
// 定義服務器監聽的端口號(4000為自定義端口,需確保未被其他服務占用)
const port = 4000;
// 啟動服務器并綁定端口(回調函數在服務啟動成功后執行)
app.listen(port, () => {// 控制臺輸出服務運行地址(便于開發者確認服務狀態和訪問路徑)console.log(`Server is running on http://localhost:${port}`);
});
2.4 靜態頁面B(b.html)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>b</title>
</head>
<body><script>// 監聽當前窗口的message事件,用于接收其他窗口發送的跨域消息window.addEventListener('message', function(event) {// 輸出消息發送方的window對象(可用于回復消息)console.log(event.source); // Window // 輸出消息發送方的源(協議+域名+端口),用于安全校驗console.log(event.origin); // http://localhost:3000// 向消息發送方返回響應消息,第二個參數指定目標源為發送方的源event.source.postMessage('world', event.origin);}, false);</script>
</body>
</html>
3 適用場景
場景類型 | 典型應用案例 |
---|---|
微前端架構 | 主應用與子應用通過 iframe 嵌套,使用 postMessage 傳遞路由、狀態等信息 |
多標簽頁同步 | 電商網站中,用戶在 A 標簽頁添加商品,B 標簽頁實時更新購物車數量 |
Web Worker 通信 | 主線程與 Web Worker 通過 postMessage 交換計算任務和結果 |
跨域文件操作 | 本地文件選擇器頁面與主應用通過 postMessage 傳遞 File 對象 |
postMessage 作為瀏覽器原生跨域方案,通過 “消息訂閱 - 發布” 模式實現了安全可控的跨窗口通信。在實際應用中,結合 Web Worker、Service Worker 等技術,可構建更復雜的跨域應用架構。如需處理高頻實時通信(如在線協作、游戲),可結合 WebSocket 方案;對于服務端跨域需求,CORS 與代理服務器仍是主流選擇。
通過合理設計消息協議與安全策略,postMessage 能在保證用戶數據安全的前提下,高效解決前端開發中的跨域通信難題。
下一章將介紹?websocket 方案 ,敬請期待!