问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

使用 WebSocket 实现跨域 iframe 通信

创作时间:
作者:
@小白创作中心

使用 WebSocket 实现跨域 iframe 通信

引用
1
来源
1.
https://cloud.tencent.com/developer/article/2415705

前言

本文是使用 WebSocket 实现跨域 iframe 通信思路实现了一个本地 Demo,功能有:

  • iframe 页面之间互相通信
  • 嵌套的 iframe 通信
  • WebSocket 客户端与服务端通信

Demo预览效果

由于完整流程操作录制的Gif图片为306M,上传图片发现掘金有限制,图片体积不能超过20M,静态图附上

页面布局

整体运行效果都是在本地运行的,启动了3个前端服务页面,分别是 8090,8091,8092
屏幕主页面是8090服务运行的,有两个卡片区可以向其他两个页面进行通信
页面中使用
iframe
嵌入了8091和8092的页面,分别是这两个卡片区,嵌入的卡片页也可以分别向其他两个页面进行数据通信

代码思路实现

目录结构

这是本地Demo的目录结构,每个服务都根据端口名进行目录区分,如果看GitHub上的源码,记得先看一下README.md文件

主页面

主页面是一个HTML单页,这里使用
http-server -p 8090
命令运行起来
HTML页面中使用
button
按钮点击分别向8091发送数据,分别使用
div
接收对应页面发送的数据

<div style="display:flex;">
    <div class="card" style="height:120px;">
        <input type="text" id="inputData" placeholder="输入数据">
        <button id="sendButton1">向页面8091发送数据</button>
        <br />
        <div>
            接收8091的数据:<div id="response1"></div>
        </div>
    </div>
    <br />
    <div class="card" style="height:120px;">
        <input type="text" id="inputData2" placeholder="输入数据">
        <button id="sendButton2">向页面8092发送数据</button>
        <div>
            接收8092的数据:<div id="response2"></div>
        </div>
    </div>
</div>
<div style="display:flex;">
    <div class="card">
        <iframe id="iframe1" src="http://localhost:8091"></iframe>
    </div>
    <div class="card">
        <iframe id="iframe2" src="http://localhost:8092"></iframe>
    </div>
</div>

在页面初始化后进行 WebSocket 进行连接,然后使用
onmessage
监听服务端发送过来的消息
注意!
这里初始化的连接地址是
ws://localhost:9000
,9000端口是WebSocket服务端,使用node运行起来的
使用
ws.send()
向其他页面发送JSON字符串消息,
sender
表示当前发送者,如:8090,
receiver
表示接收者,如:8091,
msg
为发送和接收的数据内容

const ws = new WebSocket('ws://localhost:9000');
ws.onopen = function () {
    console.log('8090页面 与 9000 WebSocket连接成功')
};
ws.onmessage = function (event) {
    console.log('8090 onmessage: ', event.data)
    if (event.data) {
        let objData = JSON.parse(event.data)
        if (objData.receiver === 8090) {
            if (objData.sender === 8091) {
                document.getElementById('response1').innerHTML = objData.msg;
            }
            if (objData.sender === 8092) {
                document.getElementById('response2').innerHTML = objData.msg;
            }
        }
    }
};
// 向8091页面发送数据
document.getElementById('sendButton1').onclick = function () {
    const data = document.getElementById('inputData').value;
    console.log('data1: ', data)
    ws.send(JSON.stringify({
        sender: 8090,
        msg: data,
        receiver: 8091
    }));
};
// 向8092页面发送数据
document.getElementById('sendButton2').onclick = function () {
    const data = document.getElementById('inputData2').value;
    console.log('data1: ', data)
    ws.send(JSON.stringify({
        sender: 8090,
        msg: data,
        receiver: 8092
    }));
};

iframe子页面

子页面有两个HTML页,分别使用
http-server -p 8091

http-server -p 8092
命令运行的,这两个页面发送数据和8090主页面实现一样,这里就不做多的介绍了,区别点在接收数据这里,接收数据使用一个

进行的接收数据展示,然后根据 sender 的来源提示不同的文字
ws.onmessage = function (evt) {
    console.log('8091 message ', evt)
    const received_msg = evt.data;
    console.log("接收到的数据: " + received_msg);
    let objData = JSON.parse(received_msg)
    console.log('objData: ', objData)
    if (objData.receiver === 8091) {
        if (objData.sender === 8090) {
            document.getElementById('response').innerHTML = "来自8090的消息: " + objData.msg;
        }
        if (objData.sender === 8092) {
            document.getElementById('response').innerHTML = "来自8092的消息: " + objData.msg;
        }
    }
};

WebSocket 服务端

服务端使用node运行,端口9000,引用了
ws
包,服务端的逻辑很简单,只提供一个socket服务,然后给所有客户端进行消息转发

let WebSocketServer = require('ws').Server;
let wss = new WebSocketServer({ port: 9000 });
let clients = [];
wss.on('connection', (ws) => {
    console.log(ws)
    clients.push(ws);
    ws.on('message', (message) => {
        console.log('received: %s', message);
        // 在这里处理接收到的消息
        // 注意!!!
        // 这里面的数据要使用 toString() 转成字符串
        // 否则客户端接收的是个 blob 对象,将无法正确解析数据
        console.log(message.toString())
        broadcast(message.toString())
    });
});
function broadcast(message) {
    clients.forEach(function (client) {
        client.send(message);
    });
}


clients
变量记录所有客户端,在接收到消息后直接转发
注意!
message.toString()
服务端的消息需使用 toString() 转成字符串,否则客户端接收的是个 blob 对象,将无法正确解析数据

http-server

使用
http-server
可以快速搭建一个简单的服务器,如果本地有 node 环境的话,执行
npm i http-server -g
全局安装即可
http-server
其他服务端程序也有类似的库,自行按需安装

完整代码地址

Front-end-function-examples/WebSocket
欢迎大家讨论交流,如果喜欢本文章或感觉文章有用,动动你那发财的小手点赞、收藏、关注再走呗
^_^

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号