在 Web 开发中过程中,同一个网址可能要在不同页面打开,页面的操作对其也有相应的影响,在管理系统中尤为常见。比如在一个列表中,我们点击新增打开了一个新的标签页,在此页面新增了一条数据,原来标签页的列表在新增后不能得到及时的反馈,需要用户手动刷新,但是通过js其实是可以实现跨标签页通信的,本文提供几种常见的方法供大家参考。
通信引用代码
jsexport default function App() { const onClick = () => { sendMsg("click", { data: "这是一段消息" }); }; useEffect(() => { listenMsg((data) => { console.log(data); }); }, []); return ( <div className="App"> <h1>跨标签页的数据共享</h1> <h2>Start editing to see some magic happen!</h2> <button onClick={onClick}>发起通信</button> </div> );}
1. BroadCast Channel
Broadcast Channel API 可以实现同 源 下浏览器不同窗口,Tab 页,frame 或者 iframe 下的 浏览器上下文 (通常是同一个网站下不同的页面) 之间的简单通讯。
广播频道会被命名和绑定到指定的源。
通过创建一个监听某个频道下的 BroadcastChannel
对象,你可以接收发送给该频道的所有消息。一个有意思的点是,你不需要再维护需要通信的 iframe 或 worker 的索引。它们可以通过构造 BroadcastChannel
来简单地"订阅"特定频道,并在它们之间进行全双工(双向)通信。
js
const channel = new BroadcastChannel("echo_channel");
export const sendMsg = (type, content) => {
console.log("-------发起通信--------", content);
channel.postMessage({
type,
content
});
};
export const listenMsg = (callback) => {
channel.addEventListener("message", (event) => {
callback && callback(event.data);
});
};
2. LocalStorage
只读的localStorage
属性允许你访问一个Document
源(origin)的对象 Storage
;存储的数据将保存在浏览器会话中。
js
export const sendMsg = (type, content) => {
console.log("-------发起通信--------", content);
localStorage.setItem(
"echo-msg",
JSON.stringify({
type,
...content
})
);
};
export const listenMsg = (callback) => {
window.addEventListener("storage", (event) => {
console.log(event);
const { newValue } = event;
try {
const msg = JSON.parse(newValue);
callback && callback(msg);
} catch (err) {
// 处理错误
}
}
});
};
3. Window.postMessage
window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为 https),端口号(443 为 https 的默认值),以及主机 (两个页面的模数 Document.domain
设置为相同的值) 时,这两个脚本才能相互通信
js
export const sendMsg = (type, content) => {
console.log("-------发起通信--------", content);
// let receiver = document.getElementById('receiver').contentWindow;
// window.parent.postMessage(JSON.stringify({
// from: 'auth',
// event: 'close',
// code: 1
// }), '*')
let receiver = window.open("https://lhp8dw.csb.app/");
receiver.postMessage({ type, content });
};
export const listenMsg = (callback) => {
window.addEventListener("message", (event) => {
callback && callback(event);
});
};
4. Service Worker
Service worker 是一个注册在指定源和路径下的事件驱动 worker。它采用 JavaScript 文件的形式,控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。
Service worker 运行在 worker 上下文:因此它无法访问 DOM,相对于驱动应用的主 JavaScript 线程,它运行在其他线程中,所以不会造成阻塞。它被设计为完全异步;因此,同步 XHR 和 Web Storage 不能在 service worker 中使用。
5. SharedWorker 定时轮询
SharedWorker
接口代表一种特定类型的 worker,可以从几个浏览上下文中访问,例如几个窗口、iframe 或其他 worker。它们实现一个不同于普通 worker 的接口,具有不同的全局作用域,
6. IndexedDB 定时轮询
IndexedDB 是一种底层 API,用于在客户端存储大量的结构化数据(也包括文件/二进制大型对象(blobs))
js
const request = indexedDB.open("database", 1);
export const sendMsg = (type, content) => {
console.log("-------发起通信--------", content);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const objectStore = db.createObjectStore("dataStore", {
keyPath: "key",
});
};
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(["dataStore"], "readwrite");
const objectStore = transaction.objectStore("dataStore");
// 存储数据
objectStore.put({ key: "supper", value: `moment` });
transaction.oncomplete = () => {
db.close();
};
};
export const listenMsg = (callback) => {
setInterval(() => {
request.onsuccess = (event) => {
const db = event.target.result;
const transaction = db.transaction(["dataStore"], "readonly");
const objectStore = transaction.objectStore("dataStore");
// 获取数据
const getRequest = objectStore.get("supper");
getRequest.onsuccess = (event) => {
const data = event.target.result;
if (data && callback) {
callback(data.value);
}
};
transaction.oncomplete = () => {
db.close();
};
};
1000
);
});
};
7. Cookie 定时轮询
js
export const sendMsg = (type, content) => {
console.log("-------发起通信--------", content);
document.cookie = `${type}=${content}`;
};
export const listenMsg = (callback) => {
setInterval(() => {
callback && callback(document.cookie); },
1000
);
});
};
8. Websocket
WebSockets 是一种先进的技术。它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此 API,你可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。