iframe父子组件通信使用心得

300 阅读2分钟

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')
}