iframe的父子通讯

最近有个需求是在父页面打开一个弹窗,然后弹窗里面是一个iframe,在关闭弹窗时需要把iframe中的audio标签的音频链接清空和做一些其他的操作。因为以前很少接触iframe,所以对它有点陌生,在经过大佬的指点和上网查阅后找到了解决方法,于是打算写一篇博客记录下iframe之间的通讯。

先说下我那个需求的解决方案,我在父页面的关闭弹窗事件中调用window.postMessage()把关闭窗口的信息传到iframe,iframe接收到这个信息后就把音频的url重置掉。

// 父页面
  detailCancel = () => {
    // 关闭弹窗时通知iframe把当前音频的url清空
    // 首先获取iframe节点,然后
    let iframe = document.querySelector('#iframe')
    iframe.contentWindow.postMessage('close', "*")
    this.setState({
      detail_visible: false,
    });
  };

// 子页面(iframe)
    componentDidMount() {
    // 在didmount生命周期注册message的监听事件,当获取到关闭的信息时执行需要的操作
    window.addEventListener('message', (e) => {
      //接收到父页面传过来的关闭信息后把音频的url清空
      if (e.data === 'close') {
        this.setState({
          audioUrl: ''
        })
      }
    })
  }

然后说一下iframe父子通讯的另一种方式,上面提到的这个方法可以适用于父子页面不同域的情况,还有一种方法是同域间的父子通讯。

1、父传子同域通讯

父页面可以通过iframe的id或者name属性直接访问到子iframe的window对象

// 父页面
  detailCancel = () => {
    let iframe = document.querySelector('#iframe')
    // 这里改为了在父页面直接调用子iframe页面的resetAudioUrl()方法
    iframe.window.resetAudioUrl()
    this.setState({
      detail_visible: false,
    });
  };

// 子页面(iframe)
  resetAudioUrl = () => {
    this.setState({
        audioUrl: "", 
    })
  }

因为在这种情况我们是直接调用子iframe页面的方法,如果在调用时子iframe页面还没有加载完成的话时会导致页面报错的,所以上面的代码还需要在父页面的detailCancel()方法这里加一个判断此时的子页面是否加载完成了。

判断iframe是否加载完成有两种方法:

a、iframe.document.readyState == "complete"来判断

b、iframe.onload = function() {} 使用onload回调函数,把调用子iframe的执行语句放到onload的回调函数里面即可

// 父页面(优化后)
  detailCancel = () => {
    let iframe = document.querySelector('#iframe')
    // 这里改为了在父页面直接调用子iframe页面的resetAudioUrl()方法
    // 调用之前先判断子iframe是否加载完成了
    iframe.document.readyState == "complete" && iframe.window.resetAudioUrl()
    this.setState({
      detail_visible: false,
    });
  };

// 子页面(iframe)
  resetAudioUrl = () => {
    this.setState({
        audioUrl: "", 
    })
  }

2、子传父同源通讯

直接使用window.parent.要调用的父页面的方法就可以了

你可能感兴趣的:(前端,javascript,开发语言)