iframe隔离,数据同步问题

背景

A系统两个页面分别用iframe嵌入到B系统,发现A的两个页面没有关联了,数据不共享了。

原因

在将两个页面通过 iframe 嵌入到另一个系统中时,每个页面都是独立的文档,它们在浏览器中是作为独立的对象加载和渲染的。这意味着每个页面都有自己的 JavaScript 上下文和全局变量,它们互相之间不共享这些信息。

当你在一个页面中设置公共参数时,这些参数仅在该页面的 JavaScript 上下文中存在,并不能直接在另一个页面中访问。这是因为每个页面都有自己的全局对象,它们之间的变量和状态是相互隔离的。

解决方法

现在需求就是两个页面都要嵌入,并且数据还要及时同步。

1、A、B系统不同源,postMessage传参

将B系统作为中转父页面,A系统的ifram1页面发送postMessage至父页面,再由父页面发送到A系统的iframe2页面,如下图。

示例代码如下:

iframe1页面发起更新数据

js 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Frame 1</title>
</head>
<body>
    <h2>Frame 1</h2>
    <button onclick="sendMessage()">Send Message to Frame 2</button>

    <script>
        function sendMessage() {
            // 发送消息到父文档
            window.parent.postMessage('Hello from Frame 1!', 'http://example.com');
        }
    </script>
</body>
</html>

父页面接收并转发至iframe2页面

js 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Parent</title>
</head>
<body>
    <h1>Parent Page</h1>
    <iframe id="frame1" src="Frame1.html" width="300" height="200"></iframe>
    <iframe id="frame2" src="Frame2.html" width="300" height="200"></iframe>

    <script>
        // 监听来自 Frame1.html 的消息
        window.addEventListener('message', function(event) {
            // 检查消息来源
            if (event.origin !== 'http://example.com') return;

            // 更新 Frame2.html 中的参数
            var frame2 = document.getElementById('frame2');
            frame2.contentWindow.postMessage(event.data, 'http://example.com');
        });
    </script>
</body>
</html>

iframe2页面接收更新

js 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Frame 2</title>
</head>
<body>
    <h2>Frame 2</h2>
    <div id="message"></div>

    <script>
        // 监听来自父文档的消息
        window.addEventListener('message', function(event) {
            // 检查消息来源
            if (event.origin !== 'http://example.com') return;

            // 显示消息
            document.getElementById('message').textContent = event.data;
        });
    </script>
</body>
</html>

本来在A系统一个公共变量解决的事儿,嵌入进去后却要绕这么一圈才能拿到数据,未免有点太繁琐了。 后面也是将iframe2的内容直接搬到了B系统里面,只用接收显示就行了,实在不行就用上面这种方法吧。

2、A、B系统同源情况下

示例代码

ifram1页面发送

js 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Frame 1</title>
</head>
<body>
    <h2>Frame 1</h2>
    <button onclick="sendDataToFrame2()">Send Data to Frame 2</button>

    <script>
        function sendDataToFrame2() {
            var dataToSend = "Data from Frame 1";
            window.parent.sendDataFromFrame1ToFrame2(dataToSend);
        }

        // 接收来自 Frame2.html 的数据
        function receiveDataFromFrame2(data) {
            console.log("Received data from Frame 2:", data);
        }
    </script>
</body>
</html>

父页面

js 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Parent</title>
</head>
<body>
    <h1>Parent Page</h1>
    <iframe id="frame1" src="Frame1.html" width="300" height="200"></iframe>
    <iframe id="frame2" src="Frame2.html" width="300" height="200"></iframe>

    <script>
        // 在父级文档中定义函数,用于从一个子级文档发送数据到另一个子级文档
        function sendDataFromFrame1ToFrame2(data) {
            var frame2 = document.getElementById('frame2').contentWindow;
            frame2.receiveDataFromFrame1(data);
        }

        function sendDataFromFrame2ToFrame1(data) {
            var frame1 = document.getElementById('frame1').contentWindow;
            frame1.receiveDataFromFrame2(data);
        }
    </script>
</body>
</html>

iframe2页面

js 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Frame 2</title>
</head>
<body>
    <h2>Frame 2</h2>
    <button onclick="sendDataToFrame1()">Send Data to Frame 1</button>

    <script>
        function sendDataToFrame1() {
            var dataToSend = "Data from Frame 2";
            window.parent.sendDataFromFrame2ToFrame1(dataToSend);
        }

        // 接收来自 Frame1.html 的数据
        function receiveDataFromFrame1(data) {
            console.log("Received data from Frame 1:", data);
        }
    </script>
</body>
</html>

可以看到子页面是直接用window.parent调用父页面的方法,然后将发送的值当参数再传到另一个子页面的方法里,就可以获取到变化后的数据了。

两种方案都是基于中转页得以通信,还考虑过数据少的情况下使用sessionStorage,一个页面存,一个页面监听变化,有兴趣的小伙伴可以试试。

相关推荐
清汤饺子5 小时前
OpenClaw 本地部署教程 - 从 0 到 1 跑通你的第一只龙虾
前端·javascript·vibecoding
颜酱6 小时前
图的数据结构:从「多叉树」到存储与遍历
javascript·后端·算法
橙某人10 小时前
LogicFlow 小地图性能优化:从「实时克隆」到「占位缩略块」!🚀
前端·javascript·vue.js
boooooooom10 小时前
讲清 Proxy + effect + track/trigger 流程
javascript·vue.js·面试
leafyyuki10 小时前
在 Vue 项目中玩转 FullCalendar:从零搭建可交互的事件日历
前端·javascript·vue.js
豆苗学前端11 小时前
彻底讲透浏览器缓存机制,吊打面试官
前端·javascript·面试
swipe11 小时前
箭头函数与 this 面试题深度解析:从原理到实战
前端·javascript·面试
进击的尘埃13 小时前
拖拽搭建场景下的智能布局算法:栅格吸附、参考线与响应式出码
javascript
小猪努力学前端13 小时前
基于PixiJS的试玩广告开发-续篇
前端·javascript·游戏
wuhen_n13 小时前
v-model 的进阶用法:搞定复杂的父子组件数据通信
前端·javascript·vue.js