浏览器不同源的页面之间如何跨域通信
目录
- 1,需求
- 2,难点
- 3,思路
- 浏览器不同源的页面之间如何跨域通信?
- 4,实现
- 第1版
- 第2版
- 最终版
- 其他的问题
- 1,页面路径需完全一致。
- 2,事件注册问题
1,需求
现在有2个项目,页面路径不同源。
- ToC 的收银台项目
类似在PC端京东淘宝,支付最后一步的收银台页面,可以选择不同支付工具付款。
- ToB 的后台管理项目
可以对收银台项目整体做一些配置:样式,支付工具相关的等等,配置项很多。
需求
- 想要在后台管理项目中增删配置项后,能够实时预览收银台项目最终的展示效果
- 展示效果符合预期,则提交修改配置项的审批电子流
- 审批通过,上线
2,难点
因为2个项目的页面路径不同源,传递数据是个问题。
3,思路
首先,后台管理项目需要增加【预览】按钮,收银台项目需要增加【预览】页面。
-
需要后端参与。收银台项目的相关配置项,本来就是通过接口获取的。所以再增加一个预览数据的接口,在预览页面调用获取数据。
-
不需要后端参与。前端直接在2个页面之间通信。
第1种思路没有什么好说的,重点来说下第2种。
浏览器不同源的页面之间如何跨域通信?
-
通过 url 传参。最简单直接,不过传递的数据大小有限。
-
postMessage,传递的数据大小我实测可以超200MB!(不知道极限,因为没再往上测试)
简单来说,我们可以获取从当前页面A通过window.open打开的页面B的引用 targetWindowB,然后在A页面通过 targetWindowB.postMessage() 向B页面分发消息。
再介绍下 window.open
简单说明:window.open 有3个参数,我们只关注前2个
strUrl:新页面的地址strWindowName:新页面的名称,如果指定了该参数,则再次调用window.open(strUrl, strWindowName)时,不会再打开第2个新页面,而是跳转到打开的第1个页面并重新加载。(效果下面会有展示)
另外需要注意:调用window.open()方法以后,远程 URL 不会被立即载入,载入过程是异步的。
会有什么问题,看下实现过程就知道了。
4,实现
通过 vite 创建2个项目模拟,A 会向 B 发送数据。启动后的页面地址分别是:
- A页面(后台管理项目 manage)
http://localhost:5173 - B页面(收银台项目 cashier)
http://localhost:5174
第1版
A页面后台管理项目 manage
<script setup>
const cashierUrl = "http://localhost:5174";
const data = { name: "下雪天的夏风" };
let cashierWindow;function init() {cashierWindow = window.open(cashierUrl, "cashierWindow");if (cashierWindow) {cashierWindow.postMessage(data, cashierUrl);}
}
</script><template><h1>manage</h1><button @click="init">发送预览数据</button>
</template>
B页面收银台项目 cashier
<script setup>
window.addEventListener("message",function (event) {if (event.origin !== "http://localhost:5173") return;if (event.data) {console.log(event.data);}},false
);
</script><template><h1>cashier</h1>
</template>
效果:

可以看到收银台项目并没有接收到消息!
原因就是:调用window.open()方法以后,远程 URL 不会被立即载入,载入过程是异步的。
换句话说,因为B页面还没有加载完成,message 事件还没有被绑定时,A页面已经把消息发送了。
第2版
延迟发送消息。
function init() {cashierWindow = window.open(cashierUrl, "cashierWindow");setTimeout(() => {if (cashierWindow) {const data = { name: "下雪天的夏风" };cashierWindow.postMessage(data, cashierUrl);}}, 1000);
}
效果:

B页面成功收到消息!
问题来了,因为这个测试用例比较简单,所以 1s B页面就会加载完成。
可面对复杂的页面+网络问题,A页面如何知道B页面已经加载完成了(message 事件绑定了)?
答案是:此时B页面可以通过 window.opener 获取 A页面的引用,使用 postMessage 向A页面发送数据!
实现思路:
- B页面加载完成后,通过
window.opener.postMessage()向A页面发送一个约定字段。 - A页面接收到约定字段后,再向B页面发送目标数据。
最终版
A页面后台管理项目 manage
<script setup>
import { ref } from "vue";
const cashierUrl = "http://localhost:5174";
const cashierLoaded = ref(false);
let cashierWindow;function init() {cashierWindow = window.open(cashierUrl, "cashierWindow");if (cashierLoaded.value) {requestData();} else {window.addEventListener("message", receiveMessage, false);}
}function receiveMessage(event) {if (event.origin !== cashierUrl) return;cashierLoaded.value = event.data === "__done__";requestData();
}const data = { name: "下雪天的夏风" };
function requestData() {cashierWindow.postMessage(data, cashierUrl);
}
</script><template><h1>manage</h1><button @click="init">发送预览数据</button>
</template>
B页面收银台项目 cashier
<script setup>
const manageUrl = "http://localhost:5173";if (window.opener) {window.opener.postMessage("__done__", manageUrl);
}window.addEventListener("message",function (event) {if (event.origin !== manageUrl) return;if (event.data) {console.log(event.data);}},false
);
</script><template><h1>cashier</h1>
</template>
效果

其他的问题
1,页面路径需完全一致。
2个不同源页面通信时,要注意设置的 url 要完全一致才能接收到消息。例如 http://localhost:5174 和 http://localhost:5174/ 是不一样的!
2,事件注册问题
看下面的代码
function init() {cashierWindow = window.open(cashierUrl, "cashierWindow");if (cashierLoaded.value) {requestData();} else {window.addEventListener("message", receiveMessage, false);}
}function receiveMessage(event) {if (event.origin !== cashierUrl) return;cashierLoaded.value = event.data === "__done__";requestData();
}
init方法中,每次都要执行window.open吗,不能把cashierWindow保存起来调用requestData吗?
也可以这样做。但这个例子中是为了每次执行后,默认跳转到 B页面并刷新。
init方法中,每次都要注册message事件吗,万一打开的B页面加载较慢,又返回到A页面再次点击发送数据,岂不是又会再次注册事件吗?
确实会再次注册事件,不过没关系,因为注册相同的事件监听器,多余的监听器会被移除,只保留一个。参考
只保留一个的前提是:事件回调函数不能是匿名函数,否则还是会注册多个!所以把receiveMessage提取出来了。
我们来验证下最终版代码的效果:

而如果监听 message 事件这样写,
window.addEventListener("message",// function receiveMessage(event) { // 效果一样function(event) {if (event.origin !== cashierUrl) return;cashierLoaded.value = event.data === "__done__";requestData();},false);
再来看下效果:

以上。如果对你有帮助,可以点赞支持下!
相关文章:
浏览器不同源的页面之间如何跨域通信
目录 1,需求2,难点3,思路浏览器不同源的页面之间如何跨域通信? 4,实现第1版第2版最终版其他的问题1,页面路径需完全一致。2,事件注册问题 1,需求 现在有2个项目,页面路径…...
【云原生】K8S二进制搭建三:高可用配置
目录 一、部署CoreDNS二、配置高可用三、配置负载均衡四、部署 Dashboard 一、部署CoreDNS 在所有 node 节点上操作 #上传 coredns.tar 到 /opt 目录中 cd /opt docker load -i coredns.tar在 master01 节点上操作 #上传 coredns.yaml 文件到 /opt/k8s 目录中,部…...
HOT78-跳跃游戏
leetcode原题链接:跳跃游戏 题目描述 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标。 示例 1: 输入:nums [2,3,1,1,4] 输…...
HDFS中的NAMENODE元数据管理(超详细)
元数据管理 元数据是什么元数据管理概述内存元数据元数据文件fsimage内存镜像文件edits log编辑日志 namenode加载元数据文件顺序 元数据管理相关目录文件元数据相关文件VERSIONseen_txid 元数据文件查看(OIV,OEV)SecondaryNameNode介绍checkpoint机制SN…...
区块链实验室(14) - 编译FISCO-BCOS
FISCO-BCOS是一种区块链平台,与Hyperledger和Ethereum有些不同,详见FISCO BCOS 区块链 编译FISCO BCOS源码的目的是修改或者新增其中功能模块,进行对比实验,验证新想法、新创意的效果。编译的步骤很简单,按技术文档一…...
for(auto iter:vec) 及 for(auto iter:vec) 的典型用法
【算法知识点】C11 标准引入了 auto 类型说明符。它通过变量的初始值或者表达式中参与运算的数据类型来推断变量的类型。 一、for(auto iter:vec) 的典型用法 #include <bits/stdc.h> using namespace std;int main(){string s;cin>>s;for(auto t:s){cout<<…...
【iosH5开发】IOS浏览器对于Vue3 Element-plus el-input中,input.value.focus无法聚焦问题
【iosH5开发】IOS浏览器对于Vue3 Element-plus el-input中,input.value.focus无法聚焦问题 此次项目遇到了两个问题,一个是在Vue3中el-input的input.value.focus()无法触发,但是在PC或者安卓均可触发。 // 解决方案 // 单纯的触发input.val…...
【2023】华为OD机试真题Java CC++ Python JS Go-题目0257-增强的strstr
题目0257-增强的strstr 题目描述 C 语言有一个库函数: char *strstr(const char *haystack, const char *needle) ,实现在字符串 haystack 中查找第一次出现字符串 needle 的位置,如果未找到则返回 null。 现要求实现一个strstr的增强函数,可以使用带可选段的字符串来模…...
Android 解析ping回复包
目标: 已知多个字符串,形如:“64 bytes from 39.156.66.18: icmp_seq1 ttl50 time29.7 ms” 获取 总Ping时间(XX:XX:XX格式),最小时间,最大时间,平均时间,丢包率,已发送个数…...
在外地ssh远程连接家里ubuntu服务器(Coplar内网穿透)
官网:https://www.cpolar.com/ 步骤: 可以先安装ssh许可(必须先完成,完成后在局域网内就可以连接自己服务器,但还是需要安装cpolar才可以外地连接服务器),参考[B站:Linux (Ubuntu) 如何开启SSH远程登录]((…...
windows创建占用特定端口程序
默认情况下,远程桌面使用的是3389端口。如果您想将远程桌面端口更改为8005,以达到模拟程序占用端口8005的情况,可以执行以下操作: 如执行以下命令,则1,2,3步相同操作可以跳过,直接往…...
【uniapp 定位获取详细位置】
在 uniapp 中获取定位信息方法,具体如下: 1. uni.getLocation 方法(都可): uni.getLocation({type: gcj02,success: function(res) {console.log(经度: res.longitude)console.log(纬度: re…...
后端进阶之路——万字总结Spring Security与数据库集成实践(五)
前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★前端炫酷代码分享 ★ ★ uniapp-从构建到提升★ ★ 从0到英雄,vue成神之路★ ★ 解决算法,一个专栏就够了★ ★ 架…...
mysql8查看执行sql记录历史,配置开启sql历史日志general_log
1.概要说明 mysql8默认未开启sql记录历史日志。 2.配置开启general_log 2.1.查看配置 general_log:是否开启sql日志。默认为OFFlog_output:日志输出位置: FILE:输出到文件。默认值TABLE:输出到表。mysql.general_log show v…...
git 版本控制与合并
一 git概述: - Git是一种分布式版本控制系统,用于跟踪和管理软件开发项目中的代码变更。 - 它允许多人协同工作,记录代码历史变更,并轻松管理多个项目版本。 **Git的主要特点**包括: 1. **分布式系统**:…...
【力扣】23. 合并 K 个升序链表 <链表指针、堆排序、分治>
目录 【力扣】23. 合并 K 个升序链表题解方法一:暴力,先遍历取出来值到数组中排序,再生成新链表方法二:基础堆排序(使用优先队列 PriorityQueue)方法三:基础堆排序(使用优先队列 Pri…...
微信小程序真机防盗链referer问题处理
公司使用百度云存储一些资源,然后现在要做防盗链,在CDN加入Referer白名单后发现PC是正常的,微信小程序无法正常访问资源了。然后是各种查啊,然后发现是微信小程序不支持Referer的修改,且在小程序开发工具是Referer是固…...
SpringBoot集成Redisson实现延迟队列
一、场景 1、下单未支付,超过10分钟取消订单 2、货到后7天未评价,自动好评 二、实现方案 1、使用xxl-job 定时任务按时检测,实时性不高 2、使用RabitMQ的插件rabbitmq_delayed_message_exchange插件 3、 redis的过期检测 redis.conf 中…...
思想道德与法治
1【单选题】公民的基本权利是指宪法规定的公民享有的基本的、必不可少的权利。公民的基本权利有不同的类别,公民的通信自由和通信秘密属于 A、人身自由 B、经济社会权利 C、政治权利和自由 D、教育科学文化权利 您的答案:A 参考答案:A 查…...
vue3登录页面
使用了element-plus <template><div class"login-wrapper"><!-- 背景图或者视频 --><div class"background" style"width: 100%; height: 100%; position: absolute; top: 0px; left: 0px;overflow: hidden;z-index:50;&qu…...
极客老王说Agent:具备“看屏幕”能力的Agent如何击穿传统接口无法触达的业务荒原?
站在2026年4月这个“智能体元年”的节点回望,人工智能的演进已然完成了一次惊人的范式跃迁。根据最新的行业动态显示,Agent正从单纯依赖文本指令的“对话框”形态,加速向具备多模态感知、尤其是具备“看屏幕”能力的“数字员工”形态进化。在…...
**发散创新:服务端渲染(SSR)的深度实践与性能优化实战**在现代前端架构
发散创新:服务端渲染(SSR)的深度实践与性能优化实战 在现代前端架构中,服务端渲染(Server-Side Rendering, SSR) 已不再是“可选特性”,而是提升首屏加载速度、SEO友好度和用户体验的核心手段之…...
LoRa土壤监测与灌溉控制系统方案
当前农业生产中,土壤水分、温度等环境参数是影响作物生长的核心因素,传统种植模式依赖人工经验判断灌溉时机与用量,存在诸多局限。随着智慧农业、精准农业的快速发展,物联网技术在农业灌溉领域的应用日益广泛,LoRa作为…...
AA-PEG-C12/C16/C18,乙酸聚乙二醇月桂/棕榈/硬脂酸酯,一类结合了乙酸、聚乙二醇和长链烷基的化合物
一.名称英文名称:AA-PEG-C12/C16/C18,Acetic Acid-PEG-C12/C16/C18中文名称:乙酸聚乙二醇月桂/棕榈/硬脂酸酯,乙酸-PEG-月桂/棕榈/硬脂酸酯分子量:1k,2k,3.4k,5k,10k&…...
OpenClaw核心:上下文工程如何让AI更懂你?(万字源码深度解析)
我们之前说过除了记忆系统,Agent 是没什么技术难度的。 比如你自己做了个 Agent,如果只是想用他去装载几个 skill,去完成日常自媒体的选题、或者去小红书等平台上自动发发文章,那是比较简单的。 但,如果你想让这个 Age…...
雯雯的后宫-造相Z-Image-瑜伽女孩部署避坑指南:xinference.log日志错误排查大全
雯雯的后宫-造相Z-Image-瑜伽女孩部署避坑指南:xinference.log日志错误排查大全 部署一个AI文生图模型,最让人头疼的往往不是写提示词,而是服务启动时那一串串让人摸不着头脑的日志。特别是当你满怀期待地部署“雯雯的后宫-造相Z-Image-瑜伽…...
mysql备份工具选择_mysqldump对InnoDB与MyISAM支持
mysqldump默认对MyISAM用表级锁、InnoDB不启用事务快照,混合引擎必须用--lock-all-tables保证一致性,且需确保REPEATABLE READ隔离级别和ROW/MIXED binlog格式。mysqldump 默认行为对 InnoDB 和 MyISAM 完全不同默认不加任何参数时,mysqldump…...
机器人通信协议全览:30种核心技术解析
各类机器人常用通信协议抽象总结表(按协议合并,带序号)序号通信协议物理接口核心特点适用机器人场景1EtherCATRJ45微秒级延迟、纳秒级同步,实时性极强工业机器人、移动机器人(AGV/AMR)、四足机器人…...
实测2026最强Agent!非结构化数据处理谁才是王者?实在Agent深度拆解
摘要: 步入2026年,AI智能体(Agent)已从简单的对话窗口进化为具备自主规划与执行能力的“数字员工”。然而,面对企业内部占比超过80%的非结构化数据(如扫描件、复杂网页、旧系统UI、音视频等)&am…...
SecGPT-14B模型压力测试:验证OpenClaw高并发安全任务的稳定性
SecGPT-14B模型压力测试:验证OpenClaw高并发安全任务的稳定性 1. 测试背景与目标 最近在探索如何将OpenClaw与安全大模型结合,构建一个自动化安全分析助手。SecGPT-14B作为一款专注于网络安全的大模型,理论上可以处理端口扫描、日志分析等任…...
