• 如何实现浏览器多标签页tab之间的通信


    方法一: 使用localStorage实现通信

    localStorage特点:

    1、同域数据共享,跨域数据无法共享;
    2、持久化数据存储
    3、提供storage事件监听localStorage变化

    示例:
    // pageA.html 发送数据js代码
    let btn = document.querySelector('button');
    let num = 0;
    
    btn.addEventListener('click', () => {
    	localStorage.setItem('num', num++);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    // pageB.html 接收数据js代码
    window.addEventListener('storage', (e) => {
    	console.log('num旧值为:', , e.oldValue, '现值为:', e.newValue);
    });
    
    • 1
    • 2
    • 3
    • 4

    通过storage方法监听localStorage变化,获取最新的num值,控制台会实时打印num的新值和旧值。

    方法二:使用cookie

    cookie特点:

    1、同域数据共享,跨域数据无法共享
    2、存储空间较小,4kb
    3、请求时会自动携带cookie

    示例:

    发送数据的页面将数据存储于cookie

    // pageA.html 发送数据js代码
    let btn = document.querySelector('button');
    let num = 10;
    
    btn.addEventListener('click', () => {
        document.cookie = `num=${++num}`;
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    由于cookie无默认事件监听它的变化,所以需要采用定时轮询的方式去手动获取cookie的最新值。

    // pageB.html 接收数据js代码
    // 定义一个获取cookie的函数
    function getCookie(key) {  // cookieList--cookie列表,key--所获取的cookie键
        let cookiesList = document.cookie.split(';');  // 获取cookie并以;切割成若干
        const cookieArr = cookiesList.map(c => c.split('='));  // 以=切分所有的cookie键值对
        const cookieSubarr = cookieArr.filter(c => c[0].trim() == key);  // 返回符合条件的cookie
        console.log(cookieSubarr[0][1]); // 打印cookie键值对的value
        return cookieSubarr 
    }
    
    setInterval(getCookie, 1000, 'num');  // 定时轮询获取最新cookie
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    方法三:使用websocket

    websocket特点:

    1、保持连接状态,而http协议是无状态连接即请求完毕会关闭连接
    2、全双工通信,客户端和服务端平等对待,可相互通信
    3、建立在TCP协议上
    4、没有同源策略,可以跨域

    示例:

    先搭建一个websocket服务器,用于pageA和pageB的连接,执行以下指令,创建package.json文件和安装websocket插件

    npm init -y 
    npm i ws --save
    
    • 1
    • 2

    新建一个index.js文件

    // index.js
    import WebSocket, { WebSocketServer } from 'ws';
    
    const wss = new WebSocket({ port: 3000 });
    let clients = [];  // 创建保存所有已连接到服务器的客户端对象数组
    
    wss.on('connection', function(client){
    	console.log('一个客户端连接到服务器');
    	if(clients.indexOf(client) === -1) {  // 当前连接客户端不在已连接的客户端数组中,添加进数组
    		clients.push(client);
    
    		client.on('message', function(msg){  // 接收客户端发过来的消息
    			console.log('收到消息:', msg);
    			for(let c of clients) {  
    				if(c !== client) {  // 将消息发送给除自己以外的客户端
    					c.send(msg.toString());
    				}
    			}
    		})
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    // pageA.html
    // 创建websocket连接
    const ws = new WebSocket('ws://localhost:3000/')  // 协议标识符为ws,加密的话是wss,服务器是网址就是要协议之后要写的url,此处是localhost:3000
    // websocket连接成功回调
    ws.onopen = function() {
    	console.log('pageA websocket连接成功')
    }
    
    let btn = document.querySelector('button');
    let num = 10;
    
    btn.addEventListener('click', () => {
       ws.send(`客户端发送: num=${++num}`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // pageB.html
    // 创建websocket连接
    const ws = new WebSocket('ws://localhost:3000/');
    // 连接成功回调
    ws.onopen = function(){
    	console.log('pageB websocket连接成功')
    }
    // 接收服务器发过来的消息
    ws.onmessage = function(e) {
    	console.log(`页面B收到:${e.data}`)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    方法四:使用SharedWorker

    webWorker是为弥补js单线程所提出的,它可以为js提供多线程环境,sharedWorker是webWorker中的一种。

    shareWorker特点:

    1、同域数据共享,跨域数据无法共享
    2、使用port发送和接收数据
    3、如果是同一个url且是同一个js,那么只会创建一个sharedWorker,多个页面共享这个sharedWorker

    示例:

    创建并启动worker.js,处理通信的数据

    // worker.js
    const set = new Set();
    onconnect = e => {
    	const port = e.ports[0];
    	set.add(port);
    
    	// 接收信息
    	port.onmessage = e => {
    	// 发送信息
    		set.forEach(p => p.postMessage(e.data))
    	}
    	// 连接成功后先广播一条消息
    	port.postMessage('worker广播消息')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // pageA.html
    const worker = new SharedWorker('./worker.js');
    
    let btn = document.querySelector('button');
    let num = 10;
    btn.addEventListener('click', () => {
       worker.port.postMessage(`客户端发送: num=${++num}`);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    // pageB.html
    const worker = new SharedWorker('./worker.js');
    worker.port.onMessage = e => console.log(`客户端B收到消息:${e.data}`)
    
    • 1
    • 2
    • 3

    总结

    实现方式优缺点
    localStorage优点: 操作简单,易于使用,有storage事件可以监听数据变化 缺点: 跨域不能共享
    cookie优点: 操作简单,兼容性好 缺点: 跨域无法共享,无法实时监听数据变化,需要使用定时器轮询,会消耗性能
    websocket优点: 可跨域通信 缺点: 需要服务端配合
    sharedWorker优点: 理论上可以实现任何数据共享 缺点: 跨域不能共享,且兼容性较差,IE浏览器均不兼容

    总而言之,根据自身需求使用以上方法

  • 相关阅读:
    linux系统上禁用ipv6
    【应用程序代理对象ApplicationDelegate-应用程序启动过程介绍 Objective-C语言】
    【智能家居】5、主流程设计以及外设框架编写与测试
    面试题c/c++ --STL 算法与数据结构
    【pytorch笔记】第七篇 最大池化层和非线性激活
    PostgreSQL 查询语句大全
    electron打包时资源下载失败cannot resolve xxx/30.0.9/electron-v30.0.9-win32-ia32.zip
    Centos7 安装gdal历程,使用node-gdal功能
    idea远程调试debug
    【C语言】19-指针-1
  • 原文地址:https://blog.csdn.net/weixin_42178670/article/details/127439755