一、前言
最近需求有跨标签页操作,借此总结跨窗口(标签页)通信的常用方法,包括同源和跨域两种情况,给出的示例代码能让你快速上手。
二、同源
localStorage 配合 storage 事件:简单、兼容性好
1window.addEventListener('storage', (e) => {
2
3 if (e.key != 'wc') return;
4 const data = JSON.parse(e.newValue);
5 console.log(data);
6});
7
8const data = {
9 a: 111,
10 now: Date.now(),
11};
12localStorage.setItem('wc', JSON.stringify(data));
Broadcast Channel API:功能全
1
2const channel = new BroadcastChannel('test_channel');
3
4channel.addEventListener('message', (e) => {
5 console.log(e.data);
6});
7
8channel.addEventListener('messageerror', (e) => {
9 console.error(e);
10});
11
12channel.postMessage({
13 url: location.href,
14 data: '123',
15});
16
17
三、跨域
利用 iframe 的 postmessage 接口
parent.html
(注意修改子页面的 iframe 地址)
1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset='UTF-8'>
5 <meta name="viewport" content="width=device-width,initial-scale=1" />
6 <title>Document</title>
7 <style>
8 #theIframe {
9 width: 450px;
10 height: 200px;
11 }
12 </style>
13</head>
14<body>
15 <h1>Parent</h1>
16 <button id="sendBtn">发送消息给子页面</button>
17 <p>收到消息:<span id="msg"></span></p>
18
19 <iframe src="http://localhost:7002/iframe/child.html" id="theIframe"></iframe>
20
21 <script>
22
23 const IFRAME_SOURCE = 'http://localhost:7002';
24
25 theIframe.addEventListener('load', () => {
26 try {
27
28 theIframe.contentDocument.body.prepend("Hello, world!");
29 } catch (err) {
30 console.log('iframe 跨域');
31 }
32
33 sendBtn.addEventListener('click', () => {
34
35 theIframe.contentWindow.postMessage({ command: 'show-text', text: '1' }, IFRAME_SOURCE);
36 });
37 });
38
39
40 window.addEventListener('message', (e) => {
41
42 if (e.origin !== IFRAME_SOURCE) return;
43
44
45 const { command, text } = e.data;
46 switch (command) {
47 case 'show-text':
48 msg.textContent = text;
49 break;
50 }
51 });
52 </script>
53</body>
54</html>
55
child.html
1<!DOCTYPE html>
2<html>
3<head>
4 <meta charset='UTF-8'>
5 <meta name="viewport" content="width=device-width,initial-scale=1" />
6 <title>Document</title>
7</head>
8<body>
9 <h1>Child</h1>
10 <button id="sendBtn">发送消息给父页面</button>
11 <p>收到消息:<span id="msg"></span></p>
12
13 <script>
14
15 const PARENT_SOURCE = 'http://localhost:7001';
16
17 sendBtn.addEventListener('click', () => {
18
19 window.parent.postMessage({ command: 'show-text', text: '3' }, PARENT_SOURCE);
20 });
21
22
23 window.addEventListener('message', (e) => {
24 if (e.origin !== PARENT_SOURCE) return;
25 const { command, text } = e.data;
26 switch (command) {
27 case 'show-text':
28 msg.textContent = text;
29 break;
30 }
31
32
33 setTimeout(() => {
34 e.source.postMessage({ command: 'show-text', text: '2' }, e.origin);
35 }, 1000);
36 });
37 </script>
38</body>
39</html>
40
启动示例:
1启动子页面服务:npx serve -l 7002
2启动父页面服务:npx serve -l 7001
3最后访问父页面即可。
如果帮到你了,可以点个赞,欢迎交流沟通。
个人笔记记录 2021 ~ 2025