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

news2024/12/23 6:15:26

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.coloradmin.cn/o/1405113.html

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

相关文章

Java 数据结构篇-实现红黑树的核心方法

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 红黑树的说明 2.0 红黑树的特性 3.0 红黑树的成员变量及其构造方法 4.0 实现红黑树的核心方法 4.1 红黑树内部类的核心方法 &#xff08;1&#xff09;判断当前…

k8s中服务器容器tcp连接数量优化

netty的http1服务器在运行一段时间后会无法提供服务&#xff0c;返回客户端socket hang up 使用apipost测试抓包显示三次握手后被reset 客户端使用了大量短连接&#xff0c;如果能改成长连接就会消耗更少的连接&#xff0c;但是客户端逻辑无法掌控&#xff0c;只能修改服务器。…

网络安全概述---笔记总结

网络安全概述 网络安全---Cyberspace security 2003年美国提出网络空间的概念 --- 一个由信息基础设施组成的互相依赖的网络。我国官方文件定义&#xff1a;网络空间为继海&#xff0c;陆&#xff0c;空&#xff0c;天以外的第五大人类活动领域 发展阶段&#xff1a; 通信保…

学习STM32,该用哪款开发工具?

有很多初学者在问&#xff1a;学习STM32&#xff0c;该用哪款开发工具&#xff1f; 我首先说一下我的观点&#xff1a; 1.没有最好&#xff0c;只有适不适合&#xff0c;适合自己的才是最好的。 2.开发工具很多&#xff0c;各有各的特点&#xff0c;有优点肯定也有缺点。 本文…

MySQL InnoDB 底层数据存储

InnoDB 页记录Page Directory记录迁移 页 是内存与磁盘交互的基本单位&#xff0c;16kb。 比如&#xff0c;查询的时候&#xff0c;并不是只从磁盘读取某条记录&#xff0c;而是记录所在的页 记录 记录的物理插入是随机的&#xff0c;就是在磁盘上的位置是无序的。但是在页中…

vscode连不上虚拟机,一直密码错误

最近在做毕设&#xff0c;但是vscode使用连接不上虚拟机&#xff0c;我以为是网络配置的问题&#xff0c;一顿查阅没找到原因。 后来查了一下ssh的日志&#xff0c;发现ssh有消息&#xff0c;但是也提示密码错误。 没找到密码配置格式什么的&#xff0c;经查看sshd配置文件发现…

easyexcel导入合并单元格解析(纵向合并,横向合并都支持)

1、按照开发逻辑&#xff0c;首先定义导入接收实体 package com.wang.test.excel;import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data;/***/ Data public class ExcelData1 {ExcelProperty(index 0)private String name;ExcelProperty(index 1)private S…

[C++] external “C“的作用和使用场景(案例)

C中extern "C"的作用是什么&#xff1f; 在 C 中&#xff0c;extern "C" 的作用是告诉编译器按照 C 语言的规范来处理函数名和变量名。这是因为 C 编译器会对函数名和变量名进行名称修饰(name mangling)&#xff0c;以区分不同的函数和变量。而在 C 语言中…

企业需要的3种供应商管理解决方案

传统的 "管理和监控 "供应商管理解决方案是对时间和金钱的巨大浪费。准入、资格认证和细分等孤立的供应商管理流程无法与其他采购流程整合在一起。 此外&#xff0c;从多个来源获取和管理供应商数据的过程只会增加固有的复杂性。而且&#xff0c;人工操作往往会延误…

【Java IO】设计模式 (装饰者模式)

Java I/O 使用了装饰者模式来实现。 装饰者模式 请参考装饰者模式详解 装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component)&#xff0c;具体组件的方法实现不需要依赖于其它对象&#xff0c;而装饰者组合了一个组件&#xff0c;这样它可以装饰其它装饰者…

Linux中文件IO(open、read、write、close函数使用)

介绍 什么是文件IO&#xff1f; 是操作系统提供的API接口函数。 POSIX接口 &#xff08;了解&#xff09; 注意&#xff1a;文件IO不提供缓冲机制 文件IO的API open close read read 文件描述符概念&#xff1a; 英文&#xff1a;缩写fd&#xff08;file descriptor&#xff…

前端和后端之间的CORS 跨域和解决办法

什么是CORS&#xff08;Cross-Origin Resource Sharing&#xff0c;跨源资源共享&#xff09; 跨源资源共享&#xff08;CORS&#xff0c;或通俗地译为跨域资源共享&#xff09;是一种基于 HTTP 头的机制&#xff0c;该机制通过允许服务器标示除了它自己以外的其他源&#xff0…

go 语言中 json.Unmarshal([]byte(jsonbuff), j) 字节切片得使用场景

struct_tag的使用 在上面的例子看到&#xff0c;我们根据结构体生成的json的key都是大写的&#xff0c;因为结构体名字在go语言中不大写的话&#xff0c;又没有访问权限&#xff0c;这种问题会影响到我们对json的key的名字&#xff0c;所以go官方给出了struct_tag的方法去修改…

【C++杂货铺】三分钟彻底搞懂如何使用C++中max函数

&#x1f308;前言 欢迎收看本期【C杂货铺】&#xff0c;这期内容&#xff0c;我们将围绕C中max函数部分进行讲解&#xff0c;包含了如何查询库函数&#xff0c;max函数的使用方法灯。如果你想学习C&#xff0c;或者刚学完C语言衔接C&#xff0c;那么这篇文章将会非常有效的帮助…

Redis学习——入门篇①

Redis学习——入门篇① 1、2&#xff1a;Redis入门概述3&#xff1a;Redis安装配置10 安装Redis-cli命令 4&#xff1a;Redis——十大数据类型11 redis数据类型12 命令查阅13 key常用命令介绍14 类型大小写和帮助命令15 String 命令&#xff08;上&#xff09;16 String 命令&a…

电脑摄像头设置在哪里?这3种打开方式要记好!

“我需要开一个视频会议&#xff0c;因此可能需要用到电脑的摄像头。但是我不知道我电脑的摄像头设置在哪里&#xff0c;有没有朋友可以告诉我一下呀&#xff1f;” 在日常办公时&#xff0c;我们可能经常要用到电脑摄像头。这不仅为用户提供了实时沟通的机会&#xff0c;还帮助…

机器学习实验报告——APRIORI算法

目录 一、算法介绍 1.1算法背景 1.2算法引入 1.3算法假设 1.4算法基本概念介绍 1.4.1关联规则 1.4.2支持度 1.4.3置信度 1.4.4频繁项集 1.4.5项目 1.4.6提升度 二、算法原理 2.1算法思想 2.2Apriori算法产生频繁项集 2.3Apriori算法的基本步骤 2.4关联分析 三、算法实现 3.1 Ap…

安卓自动化 | autox.js

介绍: 不需要Root权限 的 JavaScript 自动化软件 官方文档: http://doc.autoxjs.com/ 开发准备 安装Releases kkevsekk1/AutoX (github.com)到手机上 安装vscode插件 插件介绍中有中文的使用说明, 如何连接电脑 Usage Step 1 按 CtrlShiftP 或点击"查看"->&…

司铭宇老师:房地产中介培训班:房地产中介培训课程

房地产中介培训班&#xff1a;房地产中介培训课程 在竞争激烈的房地产市场中&#xff0c;成为一名杰出的中介代表不仅需要对行业有深刻的理解&#xff0c;还要具备一系列专业技能和高效的销售策略。我们的房地产中介培训课程旨在为有志于提升个人能力和业绩的中介人员提供全面、…

C++: vector

目录 1.vector的介绍 2.vector常用的接口 1.vector构造 2.迭代器iterator的使用 3.vector空间增长 4.vector的增删改查 3.vector模拟实现 如果在reverse时使用memcpy会怎么样&#xff1f; 1.vector的介绍 C中的vector是一个动态数组容器&#xff0c;可以存储任意类型的…