首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用 WebSocket 实现跨域 iframe 通信

使用 WebSocket 实现跨域 iframe 通信

原创
作者头像
草帽lufei
发布2024-05-08 13:56:48
发布2024-05-08 13:56:48
5430
举报
文章被收录于专栏:程序语言交流程序语言交流

宫崎骏风-罗罗诺亚·索隆

前言

本文是使用 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接收对应页面发送的数据

代码语言:html
复制
<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 为发送和接收的数据内容

代码语言:js
复制
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 8091http-server -p 8092 命令运行的,这两个页面发送数据和8090主页面实现一样,这里就不做多的介绍了,区别点在接收数据这里,接收数据使用一个 <div id="response"></div> 进行的接收数据展示,然后根据 sender 的来源提示不同的文字

代码语言:js
复制
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服务,然后给所有客户端进行消息转发

代码语言:js
复制
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

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

微信公众号:草帽Lufei

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 宫崎骏风-罗罗诺亚·索隆
  • 前言
  • Demo预览效果
  • 页面布局
  • 代码思路实现
    • 目录结构
    • 主页面
    • iframe子页面
    • WebSocket 服务端
  • http-server
  • 完整代码地址
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档