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

浏览器内多个标签页之间通信,通俗的讲就是浏览器中开了多个窗口,在其中一个窗口做了一些行为等其他窗口不用刷新也能有相关表现。

一、cookie+setInterval方式

要想在多个窗口中通信,通信的内容一定不能放在window对象中,因为window是当前窗口的作用域,里面的内容只属于当前窗口。而cookie是浏览器的本地存储机制,和窗口无关。

将要发送的信息写入cookie:

 var msg = documet.querySelector('#msg');
 if(msg.value.trim() != ""){
 	docment.cookie = "msg=" + msg.value.trim();
 }

在另一个页面读取cookie:

 var recMsg = document.querySelector('#recMsg');
 function getValue(key){
	var cookies = '{"'+document.cookie.replace(/=/g,'":"').replace(/;\s+/g,'", "')+'"}';
    cookies = JSON.parse(cookies);
    return cookies[key];
 }
 setInterval(function(){
    recMsg.innerHTML = getValue("msg1");
 },500);

但是由于仅仅从cookie读取信息不能实时更新,需要手动刷新,因此采用setInterval定时器解决,将读取信息的代码封装成一个函数,在定时器内调用即可

缺点:

1)cookie空间有限,容量4k
2)每次http请求都会把当前域的cookie发送到服务器上,浪费带宽
3)setInterval评率设置过大会影响浏览器性能,过小会影响时效性

优点:每个浏览器都兼容

二、websocket协议

websocket是一种网络通信协议,因为http有缺陷,通信只可以由客户端发起,服务器无法主动向客户端发送消息,但如果这时服务器有连续变化的状态,那么就只能使用轮询(每个一段时间,就发出一个询问)的方式来询问。因为websocket拥有全双工(full-duplex)通信自然可以实现多个标签页之间的通信。
发送方先发送消息到WebSocketServer,然后服务端再实时把消息发给接收方

用法:新建webSocket文件夹,在该目录下打开终端,运行npm initnpm安装及配置步骤)初始化一个简单的node项目(因为需要引入ws包),一直按回车到结束就初始了一个简单的node项目。再安装ws包,依旧在当前目录下的终端运行npm i -save ws,在webSocket目录下新建sever.js、send.html、reveive.html文件
在这里插入图片描述

//server.js
//获得WebSocketServer类型
var WebSocketServer = require('ws').Server;
//创建WebSocketServer对象实例,监听指定端口
var wss = new WebSocketServer({ host: '本机ip地址', port: 8080 }, () => {
    console.log('success');
});
//创建保存所有已连接到服务器的客户端对象的数组
var clients = [];
//为服务器添加connection事件监听,当有客户端连接到服务端时,立刻将客户端对象保存进数组中。
wss.on('connection', function (client) {
    console.log("一个客户端连接到服务器");
    // 如果没有这个client对象,说明是第一次连接,就加入到clients中
    if (clients.indexOf(client) === -1) {
        clients.push(client);
        console.log("有" + clients.length + "个客户端在线");
        //为每个client对象绑定message事件,当某个客户端发来消息时,自动触发
        client.on('message', function (msg) {
            console.log("收到消息:" + msg);
            //遍历clients数组中每个其他客户端对象,并发送消息给其他客户端
            for (var c of clients) {
                if (c != client) {
                    c.send(msg);
                }
            }
        });
    }
});
<!-- send.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body style="text-align: right">
    <input id="msg" type="text">
    <button id="send">发送</button>
    <script>
        //建立到服务端webSocket连接
        var ws = new WebSocket("ws://本机ip地址:8080");
        send.onclick = function () {
            if (msg.value.trim() !== "") {
                // 将消息发到服务器
                ws.send(msg.value.trim());
            }
        }
    </script>
</body>

</html>
<!-- receive.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h1>收到消息: <span id="recMsg"></span></h1>
    <script>
        var recMsg = document.querySelector('#recMsg');
        // 新建FileReader实例
        var reader = new FileReader();
        //建立到服务端webSocket连接
        var ws = new WebSocket("ws://192.168.56.1:8080");
        //当连接被打开时,注册接收消息的处理函数
        ws.onopen = function (event) {
            //当有消息发过来时,就将消息放到显示元素上
            ws.onmessage = function (event) {
                console.log(event.data);
                // event.data是Blob类型,需要转换成字符串输出
                reader.readAsText(event.data);
                reader.onload = function (e) {
                    recMsg.innerHTML = reader.result;
                }
            }
        }
    </script>
</body>

</html>

缺点:需要服务端的支持才能完成任务,如果socket数据量比较大的话,会严重消耗服务器的资源;必须要在服务端项目中写服务端监听程序才能支持。

优点:使用简单,功能灵活,强大,如果部署了WebSocket服务器,可以实现很多实时的功能。

三、localstorage

localStorage比cookie好在它在setItem存东西时会自动触发整个浏览器的storage事件,除了当前页面之外,所有打开的标签窗口都会受影响。

<!-- send.html -->
<body style="text-align: right">
  <input id="msg1" type="text"> 
  <input id="msg2" type="text"> 
  <button id="send">发送</button>
  <script>
    send.onclick = function(){
      if(msg1.value.trim()!=="" && msg2.value.trim()!==""){
        localStorage.setItem("msg1",msg1.value.trim());
        localStorage.setItem("msg2",msg2.value.trim());
      }
    }
  </script>
</body>
<!-- receive.html -->
<body>
  <h1>收到消息:<span id="recMsg"></span></h1>
  <script>
    function load(){
      recMsg.innerHTML = localStorage.getItem("msg1");
    }
    load();
    // 任何页面修改了localStorage的值,都会自动触发其他页面中的storage事件
    // 只要storage一变化我们读取localStorage中对应的值显示到页面上
    window.addEventListener("storage",function(){
      load();
    });
  </script>
</body>

缺点:localStorage是h5属性,高版本浏览器才支持,而且不同浏览器的localStorage大小限制不统一;localStorage只能监听非己页面的数据变化

优点:解决了cookie容量小和时效性问题

四、html5浏览器新特性——SharedWorker

  • WebWorker的升级版,webworker只能在一个窗口内使用,而SharedWorker可以在多个窗口之间通信
  • SharedWorker也是纯客户端的,没有服务端参与
  • SharedWorker在客户端有一个自己维护的对象worker.js,消息存储在worker.js的data中
  • SharedWorker不如localStorage的是接收消息不是自动的,也要用定时器实时从worker.js中获取消息

(worker.js文件暂时有问题待解决)

 // worker.js文件
//在所有SharedWorker共享的worker.js中,保存一个data变量,用于存储多个worker共享的数据
let data = '';
//必须提供一个名为onconnect的事件处理函数
//每当一个页面中new SharedWorker("worker.js")时,就会为新创建的worker绑定onconnect事件处理函数
onconnect = function (e) {
    //获得当前连接上来的客户端对象
    var client = e.ports[0];
    // client.postMessage(data);
    //当当前对象收到消息时
    client.onmessage = function (e) {

        //如果消息内容为空,说明该客户端想获取共享的数据data
        if (e.data === "") {
            //就给当前客户端发送data数据
            client.postMessage(data);
        } else {//否则如果消息内容不为空,说明该客户端想要提供新的消息保存在共享的data中,供别人获取
            data = e.data;
        }
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<!-- send.html文件 -->

<body>
    <input type="text" id="msg"><button id="send">发送</button>
    <script>
        var msg = document.querySelector('#msg');
        var worker = new SharedWorker("./worker.js");
        worker.port.start();
        send.onclick = function () {
            if (msg.value.trim() !== "") {
                console.log(msg.value.trim());
                worker.port.postMessage(msg.value.trim());
            }
        }
    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<!-- receive.html文件 -->

<body>
    <h1>收到消息:<span id="recMsg"></span></h1>
    <script>
        var recMsg = document.querySelector('#recMsg');
        var worker = new SharedWorker("./worker.js");
        //3. 当worker.js中给当前客户端返回了data,会触发当前客户端的message事件。data的值,自动保存进事件对象e的data属性中
        worker.port.addEventListener("message", function (e) {
            recMsg.innerHTML = e.data;
        })
        worker.port.start();
        //1. 接收端反复向共享的worker.js对象中发送空消息,意为想获取data的值
        setInterval(function () {
            console.log("请求接收信息");
            worker.port.postMessage("");
            //2. 只要发送消息,就触发worker.js中的onmessage,onmessage判断是空消息内容,说明客户端想获得data。于是就用postMessage()方法,将data返回给当前客户端
        }, 500);
    </script>
</body>

</html>
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Zero Clipboard的实现原理 Zero Clipboard 利用透明的Flash让其漂浮在复制按钮之上,这样其实点击的不是按钮而是 Flash ,这样将需要的内容传入Flash,再通过Flash的复制功能把传入的内容复制到剪贴板。 Zero Clipboard的安装方法 首先需要下载 Zero Clipboard的压缩包,解压后把文件夹中两个文件:ZeroClipboard.js 和 ZeroClipboard.swf 放入到你的项目中。 然后把在你要使用复制功能的面中引入Zero Clipboard的js文件:ZeroClipboard.js 如下代码: [removed][removed] 注意:以上 ZeroClipboard.js, ZeroClipboard.swf需要放在同一路径下。如果不在同一路径,可使用ZeroClipboard.setMoviePath( “Flash路径” );来设置ZeroClipboard.swf 地址 Zero Clipboard实现简单跨浏览器复制 var clip = new ZeroClipboard.Client(); // 新建一个对象 clip.setHandCursor( true ); // 设置鼠标为手型 clip.setText("哈哈"); // 设置要复制的文本。 // 注册一个 button,参数为 id。点击这个 button 就会复制。 //这个 button 不一定要求是一个 input 按钮,也可以是其他 DOM 元素。 clip.glue("copy-botton"); // 和上一句位置不可调换 这样,这样基本功能实现了,点击按钮就可以复制设置好的文本了。你可能注意到了,待复制的文本是固定的,如果想要动态改变的怎么办,比如复制一个输入框中的内容。不用担心,下面会讲到的。 Zero Clipboard的高级功能 1、reposition() 方法 因为按钮上漂浮有一个 Flash 按钮,所以当面大小发生变化时,Flash 按钮可能会错位,这样就点不着了。 不要紧,Zero Clipboard 提供了一个 reposition() 方法,可以重新计算 Flash 按钮的位置。我们可以将它绑定到 resize 事件上。如下面代码是在jQuery下实现的resize事件重新设置按钮位置: $(window).resize(function(){ clip.reposition(); }); 2、hide() 和 show() 方法 这两个方法可以隐藏和显示 Flash 按钮 。其中 show() 方法会调用 reposition() 方法。 3、setCSSEffects() 方法 当鼠标移到按钮上或点击时,由于有 Flash 按钮的遮挡,所以像 css “:hover”, “:active” 等伪类可能会失效。setCSSEffects() 方法就是解决这个问题。首先我们需要将伪类改成类,比如: #copy-botton:hover{border-color:#FF6633;}// 可以改成下面的 ":hover" 改成 ".hover" #copy-botton.hover{border-color:#FF6633;} 我们可以调用 clip.setCSSEffects( true ); 这样 Zero Clipboard 会自动为我们处理:将类 .hover 当成伪类 :hover 。 4、getHTML() 方法 如果你想自己实例一个 Flash ,不用 Zero Clipboard 的附着方法,那么这个方法就可以帮上忙了。它接受两个参数,分别为 Flash 的宽度和高度。返回的是 Flash 对应的 HTML 代码。例如: var html = clip.getHTML( 150, 20 ); 你可以用 innerHTML 或直接 [removed](); 进行输出。 以下是测试输出的组装完毕的HTML 代码: <embed id="ZeroClipboardMovie_1" src="zeroclipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="150" height="20" name="ZeroClipboardMovie_1" align="middle" allowScriptAccess="always" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=1&width=150&height=20" wmode="transparent" /> IE 的 Flash JavaScript 通信接口上有一个 bug 。你必须插入一个 object 标签到一个已存在的 DOM 元素中。并且在写入 innerHTML 之前请确保该元素已经 appendChild 方法插入到 DOM 中。 Zero Clipboard 事件处理 Zero Clipboard 提供了一些事件,你可以自定义函数处理这些事件。Zero Clipboard 事件处理函数为 addEventListener(); 例如当 Flash 完全载入后会触发一个事件 “load” 。 clip.addEventListener( "load", function(client) { alert("Flash 加载完毕!"); }); Zero Clipboard 会将 clip 对象作为参数传入。即上例中的 “client” 。 还有 “load” 也可以写成 “onLoad”,其他的事件也可以这样。 其他事件还包括: mouseOver 鼠标移上事件 mouseOut 鼠标移出事件 mouseDown 鼠标按下事件 mouseUp 鼠标松开事件 complete 复制成功事件 其中 mouseOver 事件和 complete 事件比较常用。 前面说过,如果需要动态改变待复制的内容,那 mouseOver 事件就可以派上用场了。例如需要动态复制一个 id 为 test 的输入框中的值,我们可以在鼠标 over 的时候重新设置值。 clip.addEventListener( "mouseOver", function(client) { var test = document.getElementById("test"); client.setText( test.value ); // 重新设置要复制的值 }); //复制成功: clip.addEventListener( "complete", function(){ alert("复制成功!"); });

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值