web客户端开发:使用Layui框架的layer进行跨域(跨iframe)数据传输遇到的问题及解决记录

一、遇到问题简述:

在一个html页面(记为A.html)中,通过layer弹出iframe层,在iframe层(子页面,记为B.html)进行数据修改,然后将修改后的最新数据从子页面(B.html)回传到父页面(A.html),

在数据回传时,通过控制台调试,发现遇到“Blocked a frame with origin”的错误。

 

二、解决方法:

通过使用postMessage方法可以安全地跨iframe进行通信。

具体为:

1.在子页面B.html中(iframe弹出层)调用父页面A.html

// 自定义js对象  使其满足传输协议格式要求
                var myJsonObj;

                myJsonObj = {
                    "chan": 1,
                    "trigchan": 0,
                    "name": "camera1",
                    "factory": 4,
                    "type": 0,
                    "source": "/dev/video0",
                    "picquality": 85,
                    "exposure": 5000,
                    "undistort": 1,
                    "mosaic": 1,
                    "osd": 1,
                    "fec": 1,
                    "fusion": 0,
                    "enable": 1,
                    "stream": [{
                        "type": 0,
                        "fps": 10,
                        "width": 1920,
                        "height": 1080,
                        "codec": 0,
                        "bitrate": 400000,
                        "iinterval": 300,
                    }]
                };

 // 解决iframe跨域传参
// 使用iframe通过iframe子页面调用父页面或父页面调用iframe子页面时,
//因为违反了浏览器安全策略,无法跨iframe获取到另一页面的数据
                // 以上问题可通过postMessage方法安全地跨iframe进行通信。
                // iframe子页面调用父页面 即:子页面向父页面发送数据
                console.log("myJsonObj == ");
                console.log(myJsonObj);
                // data为子页面发送的数据(可以是一个js对象,会被自动序列化处理)
                window.parent.postMessage(myJsonObj, '*');

 

2. 在父页面A.html中添加数据监听方法,监听来自iframe子页面发送过来的数据

                     // 编辑操作完成后 重新赋值刷新显示table中的内容  
                    // 拿到 table/edit_video_channel_config.html 中的元素数据
                    // 父页面数据监听 来自iframe子页面发送过来的数据
                    addEventListener('message', e => {
                        // e.data为子页面发送的数据
                        console.log(e.data)

                        obj.data.chan = e.data.chan;
                        obj.data.trigchan = e.data.trigchan;
                        obj.data.name = e.data.name;
                        // obj.data.factory = e.data.factory;
                        // obj.data.type = e.data.type;
                        obj.data.source = e.data.source;
                        obj.data.enable = e.data.enable;

                        // 判断相机厂家
                        switch (e.data.factory) {
                            case 0:
                                obj.data.factory = "未知";
                                break; //可选
                            case 1:
                                obj.data.factory = "森云";
                                break; //可选
                            case 2:
                                obj.data.factory = "海康";
                                break; //可选
                            case 3:
                                obj.data.factory = "FLIR";
                                break; //可选
                            case 4:
                                obj.data.factory = "大华";
                                break; //可选
                            case 5:
                                obj.data.factory = "V412";
                                break; //可选
                            case 6:
                                obj.data.factory = "Ladybug";
                                break; //可选
                            case 7:
                                obj.data.factory = "Gige";
                                break; //可选
                            default: //可选
                                //语句
                        }

                        // 判断相机类别
                        switch (e.data.factory) {
                            case 0:
                                obj.data.type = "未知";
                                break; //可选
                            case 1:
                                obj.data.type = "UVC";
                                break; //可选
                            case 2:
                                obj.data.type = "USB工业相机";
                                break; //可选
                            case 3:
                                obj.data.type = "网络工业相机";
                                break; //可选
                            default: //可选
                                //语句
                        }


                        // 更新table中的元素数据
                        obj.update({
                            chan: obj.data.chan,
                            trigchan: obj.data.trigchan,
                            name: obj.data.name,
                            factory: obj.data.factory,
                            type: obj.data.type,
                            source: obj.data.source,
                            enable: obj.data.enable
                        });

                    })

通过以上步骤即可通过postMessage方法安全地跨iframe进行通信。

 

参考:解决iframe跨域传参(Blocked a frame with origin)

           感谢!

 

后续记录:

发现的问题:addEventListener()触发多次

在通过使用addEventListener()方法监听postMessage()回传的数据时,发现addEventListener会被重复绑定,也就是点击(执行)一次postMessage(),绑定一次触发一次,再点击(执行),再绑定触发两次,如此叠加,导致addEventListener()触发多次,使父页的table表中凡是被执行修改过的数据都被重新赋值为最后一次的相同的数据。

解决方法:

将f父页面用于监听postMessage()回传数据的方法 addEventListener()方法换onmessage()方法,即可解决addEventListener点击一次触发多次的问题。

代码如下:

原来的:

    // 父页面数据监听 来自iframe子页面发送过来的数据
    window.addEventListener('message', e => {
        //TODU    
    })

修改后的:

 window.onmessage = function(e) {
     // e.data为子页面发送的数据
    //TODU
}

 

参考:

解决addEventListener点击一次触发多次的方法

postMessage的使用

JavaScript addEventListener()事件监听方法

https://www.runoob.com/jsref/dom-obj-event.html

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在 Vue Admin 框架使用 CORS 解决问题可以通过以下步骤: 1. 安装 axios:首先,确保你的项目中已经安装了 axios,可以使用以下命令进行安装: ```bash npm install axios --save ``` 2. 创建一个 axios 实例:在你的项目中创建一个独立的 axios 实例,用于发送请求。在这个实例中,你可以设置一些默认的请求头和其他配置。 ```javascript // src/utils/axios.js import axios from 'axios'; const instance = axios.create({ baseURL: 'https://api.example.com', // 设置请求的基础URL timeout: 5000, // 设置请求超时时间 withCredentials: true, // 允许携带凭证(例如:cookies) }); export default instance; ``` 3. 在需要发送请求的地方使用 axios 实例:在你的组件或其他地方,使用创建的 axios 实例来发送请求。 ```javascript // src/views/Example.vue <template> <div> <button @click="fetchData">Fetch Data</button> </div> </template> <script> import axios from '@/utils/axios'; export default { methods: { fetchData() { axios.get('/data') .then(response => { console.log(response.data); }) .catch(error => { console.error(error); }); }, }, }; </script> ``` 在上述示例中,我们使用了创建的 axios 实例来发送 GET 请求,并访问了`/data`路径。由于我们已经在 axios 实例中设置了基础URL,实际发送的请求将是`https://api.example.com/data`。 请注意,在服务器也需要设置相应的 CORS 头来允许请求。你可以参考前面提到的服务器设置响应头部分的示例代码来设置服务器的 CORS 头。 以上是在 Vue Admin 框架使用 CORS 解决问题的一种方法,你可以根据实际需求和项目结构进行相应的调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xw-何妨吟啸且徐行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值