一、遇到问题简述:
在一个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
}
参考:
JavaScript addEventListener()事件监听方法
https://www.runoob.com/jsref/dom-obj-event.html