Iframe 父子页面通信

本文介绍了如何在Vue应用中,通过iframe实现父页面向子页面发送消息,以及子页面接收并处理来自父页面的token。着重讨论了处理异步加载和通信延迟的技术策略,确保子应用在接收到消息后再进行API请求。
摘要由CSDN通过智能技术生成

1、父发消息给子,接收来自子的消息

父页面相关代码


  <div class="iframeWrap">
    <iframe ref="udaamIframe" class="udaamIframe" style="width:100%;height:100%" :src="linkUrl" frameborder="0" />
  </div>

  data() {
    return {
      linkUrl: this.$route.meta.linkUrl
    }
  },
// vue挂载阶段
  mounted() {
    this.iframeTalk()
  },
  
  methods: {
    iframeTalk() {
    // 有这个参数 needSendToken 的才需要进行通信
      if (this.linkUrl.includes('needSendToken=true')) {
        const iframe = this.$refs.udaamIframe // 这个是vue的语法,可以用下面一行替换
        // document.querySelector('.iframeWrap .udaamIframe')
        var fatherApp = iframe.contentWindow
        // 处理兼容行问题
        if (iframe.attachEvent) {
          // 当 iframe 加载好了再发消息,不然iframe收不到
          iframe.attachEvent('onload', () => {
            this.sendToken(fatherApp)
          })
        } else {
          iframe.onload = () => {
            this.sendToken(fatherApp)
          }
        }

        window.udemrFirstLoginOut = true // 避免触发多次
        // 接收子应用消息
        window.addEventListener('message', e => {
          // <!-- 对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击 -->
          if (e.data && e.data.origin === 'child' && e.data.isLoginOut === true && window.udemrFirstLoginOut) {
            console.log('收到child发来的消息 需要协助其退出登录, e:', e)
            window.udemrFirstLoginOut = false
            store.dispatch('LogOut')
          }
        }, false)
      }
    },
    sendToken(udaamApp) {
      console.log('父 发消息给外链子应用,消息内容为token')
      udaamApp.postMessage(
        {
          type: 'sendToken',
          token: localStorage.getItem('token'),
          remark: '阿巴阿巴阿巴'
        },
        '*'
      )
    }
 }

2、子接收来自父的消息、发消息给父

子页面相关代码

// 接收来自父发来的消息
window.addEventListener('message', function(e) {
    if (e.data && e.data.type === 'sendToken') {
      console.log('收到来自主应用的消息', e)
      localStorage.setItem('token', e.data.token)
    }
  })

// 子发消息给父
  const params = {
    origin: 'child',
    isLoginOut: true
  }
  window.parent.postMessage(params, '*')

补充

由于 加载 iframe 是异步的、  iframe收到主应用发来的消息也是异步的、iframe 根据路由加载对应的模块也是异步的、对应模块加载时什么时候发起api请求也是异步;

这么多异步,已经避免的是主应用发消息一定是在iframe 加载后能收到消息后才发的消息,即子应用iframe一定能正常收到主应用的消息;  

但是子应用 iframe 收到消息 和  其页面调api请求是不可控的,而我们又需要 iframe收到消息之后再发起请求(需要携带父发来的token),所以需要处理一下:

思路如下: 找到需求发请求的模块,找出其需要最先发的请求,在发请求前先轮询等待接收主应用的消息,直到收到消息后再结束轮询正常发起api请求加载页面;
// 等待接收到主应用发来的消息后 再进行api请求(因为发请求需要携带由主应用传过来的token)
timeout: null

setWaitToken() {
      const getToken = () => {
        this.timeout && clearTimeout(this.timeout)
        this.timeout = setTimeout(() => {
          if (localStorage.token) {
            this.yourFirstApi() // 该页面需要第一个发起的api请求
          } else {
            getToken()
          }
        }, 100)
      }
      getToken()
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

#老程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值