同源
BroadcastChannel
在相同的源的浏览器上下文(windows,tabs,frames或者iframes)之间进行简单的通信
API
- 事件监听:
- (on)message: 监听到有数据发送时触发;
- (on)onmessageerror: 监听到消息错误是触发;
- 方法:
- postMessage(msg: any): 发送消息;
- close(): 关闭channel,不再接收;
发送页:
// pages/dispather.js
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { useState } from 'react';
export default function Dispather() {
const [message, setMessage] = useState('');
// 发送消息
const handleSendMessage = () => {
// new BroadcastChannel的参数发送方和接收方必须是一样的
const channel = new BroadcastChannel('this_params_must_be_same');
channel.postMessage(message);
};
return (
<div className={styles.container}>
<Head>
<title>Dispatcher</title>
</Head>
<main className={styles.main}>
<h4>This is messege to be sent:</h4>
<input
value={message}
onChange={e => {
setMessage(e.target.value);
}}
/>
<br />
<button onClick={handleSendMessage}>click to send</button>
</main>
</div>
);
}
复制代码
接收页
// pages/receiver.js
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { useEffect, useState } from 'react';
export default function Receiver() {
// --监听消息接收--
const handleListenMessage = () => {
// new BroadcastChannel的参数发送方和接收方必须是一样的
const channel = new BroadcastChannel('this_params_must_be_same');
console.log('This channel is working:', channel.name, '(channel.name)');
channel.onmessage = function (event) {
setMessage(event.data);
};
};
const [message, setMessage] = useState('');
// handleListenMessage不能直接在组件里执行,因为用的ssr,在server端没有BroadcastChannel这个API
useEffect(() => {
handleListenMessage();
}, []);
// ReferenceError: BroadcastChannel is not defined
// handleListenMessage();
return (
<div className={styles.container}>
<Head>
<title>Receiver</title>
</Head>
<main className={styles.main}>
<h4>This is messege received:</h4>
<h4>{message}</h4>
<br />
</main>
</div>
);
}
复制代码
Shared Worker
普通的 Worker 之间独立运行、数据互不相通;而多个 Tab 注册的 Shared Worker 则可以实现数据共享。
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { useState, useEffect } from 'react';
export default function Dispather() {
const [message, setMessage] = useState('');
const [worker, setWorker] = useState('');
useEffect(() => {
// new SharedWorker引用同一个脚本,名字必须要一样才能数据共享
setWorker(new SharedWorker('/worker.js', 'this_name_must_be_same'));
}, []);
// 发送消息
const handleSendMessage = () => {
worker.port.postMessage(message);
};
return (
<div className={styles.container}>
<Head>
<title>Dispatcher</title>
</Head>
<main className={styles.main}>
<h4>This is messege to be sent:</h4>
<input
value={message}
onChange={e => {
setMessage(e.target.value);
}}
/>
<br />
<button onClick={handleSendMessage}>click to send</button>
</main>
</div>
);
}
复制代码
接收页
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { useEffect, useState } from 'react';
export default function Receiver() {
const [worker, setWorker] = useState('');
useEffect(() => {
setWorker(new SharedWorker('/worker.js', 'this_name_must_be_same'));
handleListenMessage();
}, []);
// --监听消息接收--
const handleListenMessage = () => {
// new SharedWorker引用同一个worker
console.log('This worker is working:', worker);
if (worker.port) {
worker.port.onmessage = function (event) {
setMessage(event.data);
};
}
};
const [message, setMessage] = useState('');
return (
<div className={styles.container}>
<Head>
<title>Receiver</title>
</Head>
<main className={styles.main}>
<h4>This is messege received:</h4>
<h4>{message}</h4>
<br />
</main>
</div>
);
}
复制代码
worker
// public/worker.js
// worker.js
const ports = new Set();
// 链接时触发
self.onconnect = event => {
// 通过 event.ports 拿到 父线程MessageEvent,new SharedWorker时第二个参数想通被认为是同一个port
const port = event.ports[0];
console.log(
'子线程worker的connect事件在父线程port的new SharedWorker时候触发,此时的port是:',
event.ports[0],
'一共的父线程port有:',
ports
);
ports.add(port);
port.onmessage = e => {
// port.onmessage 监听父线程的消息
console.log(e.data);
console.log(
'父线程port的message事件在postMessage时候触发,此时的port是:',
port,
'message是:',
e.data,
'一共的父线程port有:',
ports,
'排除自己还有',
Array.from(ports).filter(p => p !== port)
);
Array.from(ports)
.filter(p => p !== port) // 广播消息时把自己除掉
.forEach(p => p.postMessage(e.data)); // 向链接池里的用户发送消息
};
};
复制代码
LocalStorage
同源限制
一个源共享同一个 localStorage,a.meituan.com 和 b.meituan.com 是两个域名,不能共享storage;但同源不同tab页可以共享localStorage
大小限制
localStorage的最大限制是5MB,如果存满了,再往里存东西,或者要存的东西超过了剩余容量,会存不进去并报错(QuotaExceededError)
API
-
发送
window.localStorage.setItem('localStore', JSON.stringify(message));
-
接收
window.onstorage = function (e) {if (e.key === 'localStore')const data = JSON.parse(e.newValue);};
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { useState, useEffect } from 'react';
export default function Dispather() {
const [message, setMessage] = useState('');
// 发送消息
const handleSendMessage = () => {
window.localStorage.setItem('localStore', JSON.stringify(message));
};
return (
<div className={styles.container}>
<Head>
<title>Dispatcher</title>
</Head>
<main className={styles.main}>
<h4>This is messege to be sent:</h4>
<input
value={message}
onChange={e => {
setMessage(e.target.value);
}}
/>
<br />
<button onClick={handleSendMessage}>click to send</button>
</main>
</div>
);
}
复制代码
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { useEffect, useState } from 'react';
export default function Receiver() {
useEffect(() => {
handleListenMessage();
}, []);
// --监听消息接收--
const handleListenMessage = () => {
window.onstorage = function (e) {
console.log(e);
if (e.key === 'localStore') {
const data = JSON.parse(e.newValue);
setMessage(data);
}
};
};
const [message, setMessage] = useState('');
return (
<div className={styles.container}>
<Head>
<title>Receiver</title>
</Head>
<main className={styles.main}>
<h4>This is messege received:</h4>
<h4>{message}</h4>
<br />
</main>
</div>
);
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END