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,一个页面存,一个页面监听变化,有兴趣的小伙伴可以试试。

相关推荐
Mr.Jessy2 小时前
Web APIs学习第一天:获取 DOM 对象
开发语言·前端·javascript·学习·html
午安~婉2 小时前
javaScript八股问题
开发语言·javascript·原型模式
西西学代码2 小时前
Flutter---个人信息(5)---持久化存储
java·javascript·flutter
芝麻开门-新起点2 小时前
flutter 生命周期管理:从 Widget 到 State 的完整解析
开发语言·javascript·ecmascript
ConardLi3 小时前
Easy Dataset 已经突破 11.5K Star,这次又带来多项功能更新!
前端·javascript·后端
冴羽3 小时前
10 个被严重低估的 JS 特性,直接少写 500 行代码
前端·javascript·性能优化
一 乐3 小时前
高校后勤报修系统|物业管理|基于SprinBoot+vue的高校后勤报修系统(源码+数据库+文档)
java·前端·javascript·数据库·vue.js·毕设
那年窗外下的雪.4 小时前
鸿蒙ArkUI布局与样式进阶(十五)—— 模块化 · 自定义组件 · 泛型机制深度解析
javascript·华为·typescript·harmonyos·鸿蒙·arkui
一点七加一5 小时前
Harmony鸿蒙开发0基础入门到精通Day09--JavaScript篇
开发语言·javascript·ecmascript
薛一半5 小时前
Vue3的Pinia详解
前端·javascript·vue.js