浏览器跨标签页通信

119 阅读2分钟

浏览器跨页签通信的几种常见的方法

监听localStorage

实现步骤: 页面A:

window.localStorage.setItem('open_about', Date.now()+'')
注意存储的值不能相同不然不会触发监听事件

页面B:
window.addEventListener('storage', function(e) {
  console.log('11111111',e)
})

使用Broadcast Channel API

1.定义一个channel.js


const channel = new BroadcastChannel('demo_1')

export function sendMsg(type, content) {
    channel.postMessage({
        type,
        content
    })
}

export function listenMsg(callback) {
    const handler = (e) => {
        callback && callback(e.data)
    }
    channel.addEventListener('message', handler)
    return ()=> {
        channel.removeEventListener('message', handler)
    }
}

A页面

const clickOpen = () => {
  sendMsg('key', '123')
}

B页面

listenMsg((e: Event)=> {
  console.log(e)
})

SharedWorker

1.新增sharedWorker.js


let connections = []
 
onconnect = function (e) {
  const port = e.ports[0]
  connections.push(port)
 
  port.onmessage = function (event) {
    // 广播接收到的消息给所有连接的端口
    connections.forEach(conn => {
      if (conn !== port) {
        conn.postMessage(event.data)
      }
    })
  }
 
  port.start()
}

A页面


const worker = new SharedWorker("sharedWorker.js");
const clickOpen = () => {
  worker.port.postMessage(`moment 1111`);
}


B页面

const worker = new SharedWorker("sharedWorker.js");

worker.port.start();
  
worker.port.onmessage = function (e) {
  if (e.data) {
    console.log(e.data);
    window.close()
  }
};

Service Worker

1.新增一个work.js

self.addEventListener("message", function (e) {
    e.waitUntil(
      self.clients.matchAll().then(function (clients) {
        if (!clients || clients.length === 0) {
          return;
        }
        clients.forEach(function (client) {
          client.postMessage(e.data);
        });
      })
    );
});

A页面


navigator.serviceWorker.register("worker.js").then(() => {
  console.log("注册成功");
});

const clickOpen = () => {
  navigator.serviceWorker.controller?.postMessage({
    value: `moment ${new Date()}`,
  });
}

B页面

navigator.serviceWorker.register("/worker.js").then(() => {
        console.log("注册成功");
});

navigator.serviceWorker.onmessage = function (e) {
  console.log(e.data.value);
};

Window.postMessage api

A页面


let targetWindow = window.open('http://localhost:5173/about', '_blank');

B页面

window.addEventListener('message', function(event: any) {
  // 确保消息来自预期的源
  if (event.origin !== 'http://localhost:5173') {
    return;
  }

  const message = event.data;
  console.log('Received message:', event);

});

IndexedDB

A页面

// 打开或创建 IndexedDB 数据库 
const request = indexedDB.open('messageDatabase', 1); 
request.onupgradeneeded = function(event) { 
    const db = event.target.result; // 创建一个对象存储空间用于存储消息
    db.createObjectStore('messages', { 
        keyPath: 'id', 
        autoIncrement: true }); 
    }; 
    request.onsuccess = function(event) { 
        const db = event.target.result; // 向数据库中添加一条新消息 
        const transaction = db.transaction(['messages'], 'readwrite'); 
        const objectStore = transaction.objectStore('messages'); 
        const message = { content: 'Hello from sender!' 
    }; 
    objectStore.add(message); 

    transaction.oncomplete = function() { 
        console.log('Message sent successfully!'); // 关闭数据库连接 
        db.close(); 
    }; 
}; 
request.onerror = function(event) { 
    console.error('Error opening database:', event.target.error); 
};

B页面

// 打开或创建 IndexedDB 数据库 
const request = indexedDB.open('messageDatabase', 1); 
request.onsuccess = function(event) { 
    const db = event.target.result; // 创建一个定时器,每隔一段时间轮询数据库中的消息
    setInterval(function() { // 创建一个事务 
        const transaction = db.transaction(['messages'], 'readwrite'); 
        const objectStore = transaction.objectStore('messages'); // 获取存储在对象存储中的所有消息 
        const request = objectStore.getAll(); 
        request.onsuccess = function(event) { 
            const messages = event.target.result; // 处理消息 
            messages.forEach(function(message) { 
                console.log('Received message:', message.content); // 在处理完消息后,删除该消息 
                objectStore.delete(message.id); 
           }); 
           // 关闭事务 
           transaction.oncomplete = function() { 
               console.log('Messages processed successfully!'); 
           }; 
        }; 
        request.onerror = function(event) { 
            console.error('Error retrieving messages:', event.target.error); // 关闭事务
            transaction.abort(); 
         }; 
    }, 1000); 
}; 
request.onerror = function(event) { 
    console.error('Error opening database:', event.target.error); 
};

websocket

使用服务器端存储:将需要共享的数据存储在服务器端,标签页之间通过与服务器进行通信来获取和更新数据。可以使用 AJAX、WebSocket 或其他网络通信技术来实现与服务器的数据交互。