1. 前言
最近公司需要开发一个统一的业务中心平台,需要通过自己的系统通过Ifearm标签嵌套第三方系统,在使用iframe标签时遇到了一些坑。
iframe为HTML内联框架元素,可以将另一个HTML页面嵌入到当前页面中。当需要与第三方系统进行通信的时候,需要调用window中的postMessage方法,该方法允许不同源的脚本采用异步的方法进行通信,可以实现跨文本文档、多窗口、跨域消息传递。
2. postMessage
window.postMessage方法主要有三个参数message,targetOrigin,transfer
message: 系统要发送的数据。
targetOrigin: 目标窗口的地址,当设置为 * 时表示无限制,任何的URL都允许发送。
transfer:可选参数,表示与message一起传送的Transferable对象。
3. 父子页面通信
两个不同源的页面,父页面如下:
<iframe id:'ifr' src: '子页面的url'>
当父页面需要发送信息给子页面时,
let ifr = document.getElementById('ifr');
ifr.contentWindow.postMessage(message, 子页面的url)
此时系统已经向子页面发送信息,子页面接收信息时需要设置监听来获取父页面发送的信息:
window.addEventLister('message', (e) => {
if(e) {
console.log(e.origin) //父页面URL,
console.log(e.source) // 父页面window对象,
console.log(e.data) //父页面发送的消息
}
})
当父页面向子页面发送信息时,可能由于父页面发送信息时,子页面尚未加载完成没有启动监听,导致发送信息时无法获取信息。一开始想到使用setTimeOut方法,延迟一定的时间,当页面加载完成后执行postMessage方法:
let ifr = document.getElementById('ifr');
setTimeOut(() => {
ifr.contentWindow.postMessage(message, 子页面的url)
},1000)
但这样做会导致当iframe标签加载完成后,如果父页面对子页面进行一些操作,如:隐藏一些元素之类的,会出现一闪而过的页面变化,降低用户的使用体验感。
postMessage方法传递信息如果要通过传递的数据对子页面进行控制的话,需要等到iframe标签加载完成后,马上发送数据给子页面,子页面获取数据对页面进行操作,使用window.onload方法可以避免这一问题。
let ifr = document.getElementById('ifr');
fir.onload = function () {
ifr.postMessage(message, '子页面的url')
}