浏览器跨标签页通信

61 阅读3分钟

BroadCast (受同源策略限制)

第一个页面

   <input type="text" name="" id="content">
    <button id="btn">dianji</button>
    <script >
        const content = document.getElementById('content');
        const btn = document.getElementById('btn');

        // 创建一个广播通道
        const broadcastChannel = new BroadcastChannel('channel1');

        btn.addEventListener('click', () => {
            // 发送消息
            broadcastChannel.postMessage({value:content.value});
        });
    </script>

第二个页面 (广播通道的名字要相同)

   <script >
        // 创建一个广播通道
        const broadcastChannel = new BroadcastChannel('channel1'); 
        broadcastChannel.onmessage = (e) => {
            console.log(e.data);
        }
    </script>

然后再页面一种输入值,点击按钮,查看页面二的控制台,发现收到了发过来的消息

ServiceWorker(受同源策略限制)

第一个页面

重点在于 navigator.serviceWorker 对象

    <input type="text" name="" id="content">
    <button id="btn">发送数据</button>
    <script>
        const content = document.getElementById('content');
        const btn = document.getElementById('btn');
        navigator.serviceWorker.register('./sw.js').then(()=>{
            console.log('注册成功')
        }).catch(()=>{
            console.log('注册失败')
        })
        btn.addEventListener('click', () => {
            // 发送消息
            console.log(content.value)
            navigator.serviceWorker.controller.postMessage({value:content.value});
        });
    </script>

sw.js文件

// 消息会到达这里
self.addEventListener('message',async function(event){
    console.log(event.data)
    // 获取到所有的客户端
    var clients =await self.clients.matchAll()
    console.log("clients",clients)
    clients.forEach(function(client){
        // 向所有客户端发送消息
        client.postMessage("sw.js: Hi Client, I received your message!")
    })
    // 通过event.source.postMessage()方法将消息发送回去
    // event.source.postMessage("sw.js: Hi Client, I received your message!")

})

第二个页面

    <script>
          navigator.serviceWorker.register('./sw.js').then(()=>{
            console.log('注册成功')
        }).catch(()=>{
            console.log('注册失败')
        })
        navigator.serviceWorker.addEventListener("message",function(event){
            console.log(event.data)
        })
    </script>

结果

Storage实现跨标签页通信(受到同源策略限制)

在Web Storage中,每次将一个值存储到本地存储时,就会触发一个storage事件。

通过监听页面的storage事件,就可以实现跨标签页通信

    <script>
        window.addEventListener('storage',function(e){
            console.log(e.key);
            console.log("旧值为",e.oldValue);
            console.log("新值为",e.newValue);
            console.log(e.url);
            console.log(e.storageArea);
        })
    </script>

SharedWorker

页面1,创建一个worker,发送消息

  <input type="text" name="" id="content">
    <button id="btn">dianji</button>
    <script>
        const btn = document.getElementById('btn');
        const content = document.getElementById('content');

        const worker = new SharedWorker('./worker.js');
        btn.addEventListener("click",()=>{
            console.log(content.value)
            worker.port.postMessage(content.value)
        })
    </script>

worker.js,数据的中转站,类似代理的模式

let data = ""
console.log("SharedWorker: start")
onconnect = function (event){
    const port = event.ports[0]
    console.log("SharedWorker: connect",port)
    port.onmessage= function (event){
        if(event.data === "get"){
            port.postMessage(data)
            data = ""
        }else{
            data = event.data
        }
    }
}

页面2,通过worker.port.postMessage('get'),不停地向worker获取数据

    <input type="text" id="ipt">
    <script>
        const worker = new SharedWorker('./worker.js');
        // 启动worker
        worker.port.start();
        worker.port.onmessage = (e)=>{
           if(e.data){
            console.log("来自worker的数据",e.data)
            document.getElementById('ipt').value = e.data
           }
        }
        setInterval(()=>{
            worker.port.postMessage('get')
        },1000)
    </script>

Cookie

页面1,设置cookie

 <script>
        document.cookie = "name=gao";
        console.log("cookie设置成功: ", document.cookie);
    </script>

页面2,轮询获取cookie,如果cookie发生变化,就进行一些操作

   <script>
        let cookie = document.cookie;
        console.log("cookie获取成功: ", cookie);
        setInterval(() => {
           if(document.cookie != cookie) {
               console.log("cookie发生变化: ", document.cookie);
           }
        }, 1000);
    </script>

Window.open、Window.postMessage(可以跨源)

页面1

   <button id="popBtn">弹出窗口</button>
    <input type="text" id="content">
    <button id="btn">发送数据</button>
    <script>
        let popBtn = document.getElementById("popBtn");
        let btn = document.getElementById("btn");
        let content = document.getElementById("content");
        let win = null;
        popBtn.onclick = function() {
            win = window.open("page2.html", "page2", "width=300, height=300, left=100, top=100");
        }
        btn.onclick = function() {
            win.postMessage(content.value, "*");
        }
    </script>

页面2(弹出的页面)

  <h1>这是page2</h1>
    <script>
        window.addEventListener("message", function(e) {
            console.log("接收到数据: ", e.data);
        });
</script>

结果

WebSocket(可以跨源)

1.建立一个websocket服务器

2.在页面1连接websocket服务器

3.websocket服务器内进行处理客户端发送的消息,向所有的客户端广播

4.页面2连接同一个websocket服务器,监听ws的message事件

5.获取页面1发送过来的消息

页面1

    <input type="text" id="ipt">
    <button id="send">发送消息</button>
    <script>
        const ws = new WebSocket("ws://localhost:9999");
        const send = document.getElementById("send");
        const msg = document.getElementById("ipt");
        send.onclick = function() {
            if(msg.value.trim() === "") {
                return;
            }else{
                console.log(msg.value);
                ws.send(msg.value);
            }
        }
        window.onbeforeunload = function() {
            ws.close();
        }
    </script>

wsServer.js

const wsServer = require("ws").Server;
// 创建一个websocket服务器的实例,监听端口9999
let wss = new wsServer({ port: 9999 }, () => {
  console.log("websocket服务器启动成功了,监听端口9999...");
});
const clients = [];
wss.on("connection", (client) => {
  // client代表的是当前连接的客户端
  clients.push(client);
  console.log("当前有" + clients.length + "个客户端连接了服务器");
  // 监听客户端发过来的消息
  client.on("message", (msg) => {
    console.log("客户端发过来的消息是:" + msg);
    // 广播消息
    clients.forEach((c) => {
      if (c !== client) {
        c.send(msg);
      }
    });
  });
  client.on("close", () => {
    console.log("有客户端断开了连接");
    // 将断开连接的客户端从clients中移除
    clients.splice(clients.indexOf(client), 1);
    console.log("当前还剩" + clients.length + "个客户端连接了服务器");
  });
});

页面2

  <input type="text" id="ipt">
    <script>
        // 1. 创建一个WebSocket对象
        const ws = new WebSocket("ws://localhost:9999");
        const msg = document.getElementById("ipt");
      ws.onopen = function() {
        ws.onmessage = function(event) {
            console.log(event);
            let reader = new FileReader();
            reader.onload = function() {
                console.log("Blob 数据: ", this.result);
                msg.value = this.result
            }
            reader.readAsText(event.data);
        	}
        }
    
    </script>