前端基础(三十八):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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS鸿蒙学习基础篇 - 运行第一个程序 Hello World

下载与安装DevEco Studio 古话说得好&#xff0c;“磨刀不误砍柴工”&#xff0c;对于HarmonyOS应用开发&#xff0c;我们首先得确保工具齐全。这就好比要进行HarmonyOS应用开发&#xff0c;我们需要确保已经安装了DevEco Studio&#xff0c;这是HarmonyOS的一站式集成开发环境…

打开json文件,读取里边的每一行数据,每一行数据是一个字典,使用matplotlib画图

这段代码的目的是读取 JSON 文件&#xff0c;提取关键信息&#xff0c;然后使用 Matplotlib 绘制四个子图&#xff0c;分别显示不同的指标随着 iter 变化的情况。这种图形化分析有助于直观地了解模型的性能。 画图结果如下&#xff1a; json文件格式如下&#xff1a;下面只粘贴…

linux邮件报警脚本

在日常的运维工作中&#xff0c;我们经常会对服务器的磁盘使用情况进行巡检&#xff0c;以防止磁盘爆满导致的业务故障. 如果能编写一个合理完善的监控脚本&#xff0c;当磁盘使用率达到我们设置的阀值时&#xff0c;就自动发送报警邮件&#xff0c;以便我们及时获悉到快爆满的…

【人工智能大脑】仿生学与人工智能交汇:基于MP神经网络的精准农业实践

MP神经网络&#xff0c;即McCulloch-Pitts模型&#xff08;MCP Model&#xff09;&#xff0c;是神经网络的早期形式之一&#xff0c;由Warren McCulloch和Walter Pitts在1943年提出。这个模型为现代人工神经网络的发展奠定了理论基础&#xff0c;并首次尝试模拟了生物神经元的…

导出 MySQL 数据库表结构、数据字典word设计文档

一、第一种 &#xff1a;利用sql语句查询 需要说明的是该方法应该适用很多工具&#xff0c;博主用的是navicat SELECT TABLE_NAME 表名,( i : i 1 ) AS 序号,COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHARACTER_MAXIMUM_LENGTH 长度, IS_NULLABLE…

docker容器快速安装启动ES

1、安装 docker a、使用 Homebrew 安装 brew install --cask --appdir/Applications docker b、手动下载安装 1、安装包下载地址&#xff1a;Install Docker Desktop on Mac | Docker Docs 根据自己的笔记本型号选择&#xff0c;我这边选择的是 intel chip 2、下载安装即可&a…

1.11马原总复习PART1

哲学不都是科学的 资本主义基本矛盾是 生产资料私有占有和生产社会化之间的矛盾&#xff1b;生产资料私有占有和生产社会化之间的矛盾 凝聚力量&#xff0c;思想保证&#xff0c;精神动力&#xff0c;智力支持 绝对剩余价值&#xff0c;必要劳动时间不变&#xff0c;绝对延长…

【前端相关】elementui使用el-upload组件实现自定义上传

elementui使用el-upload组件实现自定义上传 一、问题描述二、实现方式三、实现步骤3.1 方式一&#xff1a;选择后自动上传3.2 方式二&#xff1a;选择图片后手动上传3.3 拓展&#xff1a;上传文件夹 四、服务器相关接口 一、问题描述 elmentui 中的upload默认的提交行为是通过…

【蓝桥杯--图论】Dijkstra、Ballman-Ford、Spfa、Floyd

今日语录&#xff1a;每一次挑战都是一次成长的机会 文章目录 朴素DIjkstra堆优化的DijkstraBallman-FordFloydSpfa(求最短路)Spfa&#xff08;求是否含有负权&#xff09; 如上所示即为做题时应对的方法 朴素DIjkstra 引用与稠密图&#xff0c;即m<n^2 #include<iostrea…

MySQL JSON数据类型

在日常开发中&#xff0c;我们经常会在 MySQL 中使用 JSON 字段&#xff0c;比如很多表中都有 extra 字段&#xff0c;用来记录一些特殊字段&#xff0c;通过这种方式不需要更改表结构&#xff0c;使用相对灵活。 目前对于 JSON 字段的实践各个项目不尽相同&#xff0c;MySQL 表…

面试经典 150 题 - 多数元素

多数元素 给定一个大小为 n 的数组 nums &#xff0c;返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的&#xff0c;并且给定的数组总是存在多数元素。 示例 1&#xff1a; 输入&#xff1a;nums [3,2,3] 输出&#xff1…

C#,入门教程(28)——文件夹(目录)、文件读(Read)与写(Write)的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(27)——应用程序&#xff08;Application&#xff09;的基础知识https://blog.csdn.net/beijinghorn/article/details/125094837 C#知识比你的预期简单的多&#xff0c;但也远远超乎你的想象&#xff01; 与文件相关的知识&#xf…

点亮流水灯

目录 1.water_led 2.tb_water_led 50MHZ一个周期是20ns,0.5秒就是20ns0.02um0.00002ms0.000_00002s。0.5/0.000_00002s25_000_000个时钟周期&#xff0c;表示要从0计数到24_999_999 LED灯是低电平点亮&#xff0c;前0.5秒点亮第一个LED灯&#xff0c;当检测到脉冲信号点亮第二…

向量点乘(内积)

向量点乘&#xff1a;&#xff08;内积&#xff09; 点乘&#xff08;Dot Product&#xff09;的结果是点积&#xff0c;又称数量积或标量积&#xff08;Scalar Product&#xff09;。 几何意义&#xff1a; 点乘和叉乘的区别 向量乘向量得到一个数为点乘 向量乘向量得到一个…

对读取的Excel文件数据进行拆分并发请求发送到后端服务器

首先&#xff0c;我们先回顾一下文件的读取操作&#xff1a; 本地读取Excel文件并进行数据压缩传递到服务器-CSDN博客 第一步&#xff1a;根据以上博客&#xff0c;我们将原先的handleFile方法&#xff0c;改为以下内容&#xff1a; const handleFile async(e) > {conso…

从 Vscode 中远程连接 WSL 服务器:可以本地操作虚拟机

从 Vscode 中远程连接 WSL 服务器&#xff1a;可以本地操作虚拟机 1.下载 Vscode Visual Studio Code - Code Editing. Redefined 2.搜索框中输入>wsl&#xff0c;点击 WSL&#xff1a;Connect to WSL using Distro... 3.点击下载好的Ubuntu&#xff0c;当左下角出现图片同…

Linux - 安装字体库解决乱码问题

文章目录 问题描述步骤资源 问题描述 该安装方法&#xff0c;不区分中文和英文字体 Java在linux上转word文档为pdf&#xff0c; linux的字体缺失&#xff0c;导致了转出的pdf为乱码。 ● Linux将word转为pdf后出现乱码&#xff1f; ● 在linux上将word转为pdf 是乱码 ● 在lin…

多维时序 | Matlab实现CNN-GRU-Mutilhead-Attention卷积门控循环单元融合多头注意力机制多变量时间序列预测

多维时序 | Matlab实现CNN-GRU-Mutilhead-Attention卷积门控循环单元融合多头注意力机制多变量时间序列预测 目录 多维时序 | Matlab实现CNN-GRU-Mutilhead-Attention卷积门控循环单元融合多头注意力机制多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍…

有效的数独[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 请你判断一个9 x 9的数独是否有效。只需要根据以下规则&#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一…

测试C#调用OpenCvSharp和ViewFaceCore从摄像头中识别人脸

学习了基于OpenCvSharp获取摄像头数据&#xff0c;同时学习了基于ViewFaceCore的人脸识别用法&#xff0c;将这两者结合即是从摄像头中识别人脸。本文测试测试C#调用OpenCvSharp和ViewFaceCore从摄像头中识别人脸&#xff0c;并进行人脸红框标记。   新建Winform项目&#xf…