前端基础(三十八):iframe通信、浏览器跨窗口通信

iframe通信 - MessageChannel

在这里插入图片描述

<!-- index.html -->
<h3>MessageChannel</h3>
<input id="input" type="text" oninput="handleInput(this.value)" />
<hr />
<iframe src="./demo.html"></iframe><script>// 定义通信实例const { port1, port2 } = new MessageChannel();// 保存到全局[window.port1, window.port2] = [port1, port2];const input = document.getElementById('input');// port1监听port2发送的信息window.port1.onmessage = (e) => input.value = e.data;// port1发送信息port2接收信息const handleInput = value => window.port1.postMessage(value);
</script>
<!-- demo.html -->
<input id="input" type="text" oninput="handleInput(this.value)" />
<script>const input = document.getElementById('input');// port2监听port1发送的信息top.port2.onmessage = (e) => input.value = e.data;// port2发送信息port1接收信息const handleInput = value => top.port2.postMessage(value);
</script>

跨窗口通信核心源码

实现方式

  1. 通过监听本地存储实现
    • window.addEventListener("storage", (e) => { /* code... */ })
  2. 通过广播通信实现 - BroadcastChannel
    • new BroadcastChannel('xxx')

本地存储实现

在这里插入图片描述

<label for="input"><span>本地存储实现 - localStorage:</span><input id="input" type="text" oninput="handleInput(this.value)" />
</label>
<script>const input = document.getElementById('input');// 初始化表单数据input.value = localStorage.getItem('value') || '';// 监听表单输入(保存通信数据到本地存储中)const handleInput = value => localStorage.setItem('value', value);// 监听本地存储window.addEventListener("storage", (e) => e.key === 'value' && (input.value = e.newValue));
</script>

广播通信实现 - BroadcastChannel

在这里插入图片描述

<label for="input"><span>广播通信实现 - BroadcastChannel:</span><input id="input" type="text" oninput="handleInput(this.value)" />
</label><script>const input = document.getElementById('input');// 定义通信实例const broadcastChannel = new BroadcastChannel('value');// 监听通信broadcastChannel.onmessage = (e) => input.value = e.data;// 监听表单输入(发送通信数据)const handleInput = value => broadcastChannel.postMessage(value);
</script>

跨窗口通信示例1 - 矩形在不同窗口拖拽穿梭

部分位置、宽高属性含义

在这里插入图片描述

实现效果(关闭开发者模式

在这里插入图片描述

源码1

<style>.cube {position: fixed;width: 400px;height: 400px;}
</style><div class="cube"></div><script>const cube = document.querySelector('.cube');const barHeight = window.outerHeight - window.innerHeight;cube.style.backgroundColor = new URLSearchParams(location.search).get('color') || 'red';// 窗口坐标转屏幕坐标function winToScreenPosition(x, y) {return [x + window.screenX, y + window.screenY + barHeight];}// 屏幕坐标转窗口坐标function screenToWinPosition(x, y) {return [x - window.screenX, y - window.screenY - barHeight];}// 监听本地存储window.addEventListener("storage", (e) => {if(e.key === 'position') {const position = JSON.parse(e.newValue);const [x, y] = screenToWinPosition(...position);cube.style.left = `${x}px`;cube.style.top = `${y}px`;}});// 鼠标按下cube.onmousedown = (e) => {// 鼠标在cube内的x、y坐标const [cubeX, cubeY] = [e.pageX - cube.offsetLeft, e.pageY - cube.offsetTop];// 鼠标移动window.onmousemove = (e) => {// 计算出矩形左上角相对页面的位置const [x, y] = [e.pageX - cubeX, e.pageY - cubeY];cube.style.left = `${x}px`;cube.style.top = `${y}px`;// 保存相对于屏幕的坐标localStorage.setItem('position', JSON.stringify(winToScreenPosition(x, y)));}// 鼠标抬起window.onmouseup = () => {window.onmousemove = null;window.onmouseup = null;};};
</script>

源码2

<style>.cube {position: fixed;width: 400px;height: 400px;}
</style><div class="cube"></div><script>const broadcastChannel = new BroadcastChannel('position');const cube = document.querySelector('.cube');const barHeight = window.outerHeight - window.innerHeight;cube.style.backgroundColor = new URLSearchParams(location.search).get('color') || 'red';// 窗口坐标转屏幕坐标function winToScreenPosition(x, y) {return [x + window.screenX, y + window.screenY + barHeight];}// 屏幕坐标转窗口坐标function screenToWinPosition(x, y) {return [x - window.screenX, y - window.screenY - barHeight];}broadcastChannel.onmessage = (e) => {const position = e.data;const [x, y] = screenToWinPosition(...position);cube.style.left = `${x}px`;cube.style.top = `${y}px`;}// 鼠标按下cube.onmousedown = (e) => {// 鼠标在cube内的x、y坐标const [cubeX, cubeY] = [e.pageX - cube.offsetLeft, e.pageY - cube.offsetTop];// 鼠标移动window.onmousemove = (e) => {// 计算出矩形左上角相对页面的位置const [x, y] = [e.pageX - cubeX, e.pageY - cubeY];cube.style.left = `${x}px`;cube.style.top = `${y}px`;// 发送相对于屏幕的坐标broadcastChannel.postMessage(winToScreenPosition(x, y));}// 鼠标抬起window.onmouseup = () => {window.onmousemove = null;window.onmouseup = null;};};
</script>

跨窗口通信示例2 - 新建页面时新建矩形,相对于屏幕位置不变

部分位置、宽高属性含义

在这里插入图片描述

实现效果(关闭开发者模式

在这里插入图片描述

源码

<style>.cube {width: 200px;height: 200px;position: fixed;border: 1px solid red;}
</style><script>// 导航栏高度const barHeight = window.outerHeight - window.innerHeight;// 窗口坐标转屏幕坐标const winToScreenPosition = (x, y) => [x + window.screenX, y + window.screenY + barHeight];// 屏幕坐标转窗口坐标const screenToWinPosition = (x, y) => [x - window.screenX, y - window.screenY - barHeight];// 渲染元素const rendererElement = (cubes) => {// 每次渲染清空页面document.body.innerHTML = `<pre>${JSON.stringify(cubes)}</pre>`;// 循环渲染元素cubes.forEach(d => {const cube = document.createElement('div');cube.setAttribute('class', 'cube');const [x, y] = screenToWinPosition(...d.position);cube.innerText = `(${x}, ${y})`;cube.style.left = `${x}px`;cube.style.top = `${y}px`;document.body.appendChild(cube);});// 动画-监听窗体移动requestAnimationFrame(() => rendererElement(cubes));}// 获取cube数据let cubes = JSON.parse(localStorage.getItem('cubes')) || [];// 定义唯一标识,每次新建页面创建全新的唯一标识let id = cubes.length && cubes[cubes.length - 1].id;id++;// 当前cube的信息const cube = { id, position: winToScreenPosition(window.innerWidth / 2 - 100, window.innerHeight / 2 - 100) };// cube数据cubes.push(cube);// 保存cube数据localStorage.setItem('cubes', JSON.stringify(cubes));// 渲染元素rendererElement(cubes);// 监听本地存储window.addEventListener('storage', (e) => {if (e.key === 'cubes') {cubes = JSON.parse(e.newValue) || [];rendererElement(cubes);}});// 监听页面关闭(包括页面刷新)window.addEventListener('beforeunload', (e) => localStorage.setItem('cubes', JSON.stringify(cubes.filter(d => d.id !== id))));// 监听页面尺寸变化(不包含浏览器窗口的位置的监听)window.addEventListener('resize', (e) => rendererElement(cubes));
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/642460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HCIA——25FTP 的工作原理、功能、TFTP、控制连接、数据连接的选择、解答

学习目标&#xff1a; 计算机网络 1.掌握计算机网络的基本概念、基本原理和基本方法。 2.掌握计算机网络的体系结构和典型网络协议&#xff0c;了解典型网络设备的组成和特点&#xff0c;理解典型网络设备的工作原理。 3.能够运用计算机网络的基本概念、基本原理和基本方法进行…

第2章-OSI参考模型与TCP/IP模型

目录 1. 引入 2. OSI参考模型 2.1. 物理层 2.2. 数据链路层 2.3. 网络层 2.4. 传输层 2.5. 会话层 2.6. 表示层 2.7. 应用层 3. 数据的封装与解封装 4. TCP/IP模型 4.1. 背景引入 4.2. TCP/IP模型&#xff08;4层&#xff09; 4.3. 拓展 1. 引入 1&#xff09;产…

char const char* 类型的实参与LPCWSTR 类型的形参类型不兼容

点击项目->项目属性 在高级中点击字符集->选择使用多字节字符集 ———————————————————————— 如果还是显示报错&#xff0c;关闭项目&#xff0c;重新进一下项目&#xff0c; 我的当时就是找了好久&#xff0c;都是以上方法&#xff0c;然后重新…

业务连续性演练在软件中的重要性

随着现代社会对信息技术的依赖程度不断增加&#xff0c;软件系统的业务连续性变得至关重要。业务连续性演练成为保障软件系统在各种不可预测情况下能够持续运行的关键措施。本文将探讨业务连续性演练在软件中的重要性以及它为组织提供的价值。 1. 灾难恢复能力的验证 业务连续性…

5G+物联网:连接万物,重塑智慧社区,开启未来生活新纪元,助力智慧社区的革新与发展

一、5G与物联网&#xff1a;技术概述与基础 随着科技的飞速发展&#xff0c;第五代移动通信技术&#xff08;5G&#xff09;和物联网&#xff08;IoT&#xff09;已经成为当今社会的热门话题。这两项技术作为现代信息社会的核心基础设施&#xff0c;正深刻地改变着人们的生活和…

Open3D 与 Point Cloud 处理

点云基础3D数据结构点云采集方法点云处理框架点云操作 Open3D基础操作 点云基础 3D数据结构 点云&#xff08;Point Cloud&#xff09;&#xff1a; 点云是由一组离散的点构成的三维数据集合&#xff0c;每个点都包含了坐标信息 (x, y, z) 、颜色 (RGB)、类别 (cls)、强度值等…

Windows如何开启telnet

打开控制面板-----点击程序 启用windows功能 勾线telnet

pytest+allure 生成中文报告

背景 已安装pytestallure&#xff0c;生成的报告是英文 allure生成中文报告 参考&#xff1a;allure report 报告中文化及其它优化 方法1&#xff1a;直接在报告中切换中文 方法2&#xff1a;依赖系统中文语言 创建一个setting.js 文件在index.html 同级目录 // 尝试从 l…

两千字讲明白java中instanceof关键字的使用!

写在开头 在过往的内容中&#xff0c;我们讲了不少的Java关键字&#xff0c;比如final、static、this、super等等&#xff0c;Java中的关键字非常之多&#xff0c;下图是整理的关键字集合 而我们今天要学习的就是其中的instanceof关键字&#xff01; instanceof的定义 inst…

图像处理算法:白平衡、除法器、乘法器~笔记

参考&#xff1a; 基于FPGA的自动白平衡算法的实现 白平衡初探 (qq.com) FPGA自动白平衡实现步骤详解-CSDN博客 xilinx 除法ip核&#xff08;divider&#xff09; 不同模式结果和资源对比&#xff08;VHDL&ISE&#xff09;_ise除法器ip核-CSDN博客 数…

【BBuf的CUDA笔记】十三,OpenAI Triton 入门笔记一

0x0. 前言 2023年很多mlsys工作都是基于Triton来完成或者提供了Triton实现版本&#xff0c;比如现在令人熟知的FlashAttention&#xff0c;大模型推理框架lightllm&#xff0c;diffusion第三方加速库stable-fast等灯&#xff0c;以及很多mlsys的paper也开始使用Triton来实现比…

sqlmap使用教程(3)-探测注入漏洞

1、探测GET参数 以下为探测DVWA靶场low级别的sql注入&#xff0c;以下提交方式为GET&#xff0c;问号&#xff08;?&#xff09;将分隔URL和传输的数据&#xff0c;而参数之间以&相连。--auth-credadmin:password --auth-typebasic &#xff08;DVWA靶场需要登录&#xf…

C语言 小明喝饮料

题目&#xff1a;喝汽水&#xff0c;1瓶汽水1元&#xff0c;2个空瓶可以换汽水&#xff0c;给n元&#xff0c;可以喝多少汽水//理论问题&#xff0c;请勿模仿-^- #include <stdio.h> int main() {int n,ret,i;scanf("%d", &n);ret n;while (n>1){ret …

基于SpringBoot的教务管理系统设计与实现(源码+调试)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于SpringBoot的教务管…

QuestDB时序数据库快速入门

简介 QuestDB是一个开源的高性能时序数据库&#xff0c;专门用于处理时间序列相关的数据存储与查询&#xff1b; QuestDB使用列式存储模型。数据存储在表中&#xff0c;每列存储在其自己的文件和其自己的本机格式中。新数据被附加到每列的底部&#xff0c;以便能够按照与摄取…

别再局限于Android和iOS了尝试鸿蒙APP系统开发吧!

最近&#xff0c;多家互联网公司也发布了鸿蒙OS的App开发工程师的岗位&#xff0c;开启了抢人大战&#xff0c;有的企业开出了近百万的年薪招聘鸿蒙OS工程师&#xff0c;而华为甚至为鸿蒙OS资深架构师开出了100万元—160万元的年薪。 「纯血」鸿蒙开启&#xff0c;欲与 Andori…

WEBDYNPRO FPM 框架

框架搭建 1、FPM_OVP_COMPONENT 1 METHOD change_toolbar_btn .2 * enabled "ABAP_TRUE可用 ABAP_FALSE不可用3 * visibility "01不可见 02可见4 DATA: ls_btn TYPE if_fpm_ovp>ty_s_toolbar_button.5 CHECK wd_this->mo_cnr IS BOUND.6 7 TRY .8 …

2011-2022年北大数字普惠金融指数“第五期”(包括省市县)

2011-2022年北大数字普惠金融指数“第五期”&#xff08;包括省市县&#xff09; 1、时间&#xff1a;2011-2022年 其中县级的时间为2014-2022年 2、来源&#xff1a;北大数字普惠金融指数 3、范围&#xff1a;全国31省&#xff0c;337个地级市以及2800个县 4、指标&#x…

API调试?试试Apipost

你是否经常遇到接口开发过程中的各种问题&#xff1f;或许你曾为接口测试与调试的繁琐流程而烦恼。不要担心&#xff01;今天我将向大家介绍一款功能强大、易于上手的接口测试工具——Apipost&#xff0c;并带你深入了解如何玩转它&#xff0c;轻松实现接口测试与调试。 什么是…

linux更新内核

内核介绍 官网链接:https://kernel.org 内核下载库: https://mirrors.edge.kernel.org/pub/linux/kernel/ 更新软件源 rootcary:~# apt-get update rootcary:~# sudo apt-get install libncurses5-dev build-essential kernel-package flex bison libelf-dev libssl-dev 下…