跨标签页的数据共享

在 Web 开发中过程中,同一个网址可能要在不同页面打开,页面的操作对其也有相应的影响,在管理系统中尤为常见。比如在一个列表中,我们点击新增打开了一个新的标签页,在此页面新增了一条数据,原来标签页的列表在新增后不能得到及时的反馈,需要用户手动刷新,但是通过js其实是可以实现跨标签页通信的,本文提供几种常见的方法供大家参考。

通信引用代码

js 复制代码
export 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 线程,它运行在其他线程中,所以不会造成阻塞。它被设计为完全异步;因此,同步 XHRWeb 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
    );
});
};
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,你可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。

相关推荐
倾颜1 小时前
从 textarea 到 AI 输入框:用 Tiptap 实现 / 命令、@ 引用和结构化请求
前端·langchain·next.js
kyriewen3 小时前
程序员连夜带团队跑路,省了23万:这AI太贵,真的用不起了
前端·javascript·openai
kyriewen3 小时前
你写的代码没有测试,就像出门不锁门——Jest + Testing Library 从入门到不慌
前端·单元测试·jest
yuzhiboyouye4 小时前
web前端英语面试
前端·面试·状态模式
canonical_entropy5 小时前
下一代低代码渲染框架 nop-chaos-flux 的设计原则
前端·低代码·前端框架
东方小月5 小时前
5分钟搞懂Harness Engineering(驾驭工程):从提示词到AI Agent的进化之路
前端·后端·架构
我叫黑大帅6 小时前
为什么需要 @types/react?解决“无法找到模块 react 的声明文件”报错
前端·javascript·面试
之歆6 小时前
DAY_21JavaScript 深度解析:数组(Array)与函数(Function)(一)
前端·javascript
XinZong6 小时前
【AI社交】基于OpenClaw自研轻量化AI社交平台实战
前端
Le_ee7 小时前
ctfweb:php/php短标签/.haccess+图片马/XXE
开发语言·前端·php