前端爬坑日志之vue内嵌iframe并跨域通讯

由于该项目是基于底本的安卓app,做的微信h5,所以本来的运用webview的页面如今须要在vue中完成,那就是运用iframe
查看了许多许多文档,个中这一篇是很有代价的 https://gist.github.com/pboji…

下面将3天的爬坑终究以问答的体式格局总结以下:

1、Vue组件中怎样引入iframe?

2、vue怎样猎取iframe对象以及iframe内的window对象?

3、vue怎样向iframe内传送信息?

4、iframe内怎样向外部vue发送信息?

1、Vue组件中怎样引入iframe?

<template>
  <div class="act-form">
    <iframe :src="src"></iframe>
  </div>
</template>

<script>

export default {
  data () {
    return {
      src: '你的src'
    }
  }
}
</script>
如上,直接经由过程增加iframe标签,src属性绑定data中的src,第一步引入就完成了

2、vue怎样猎取iframe对象以及iframe内的window对象?

在vue中,dom操纵比不上jquery的$('#id')来的轻易,然则也有要领,就是经由过程ref
<template>
  <div class="act-form">
    <iframe :src="src" ref="iframe"></iframe>
  </div>
</template>

<script>

export default {
  data () {
    return {
      src: '你的src'
    }
  },
  mounted () {
    // 这里就拿到了iframe的对象
    console.log(this.$refs.iframe)
  }
}
</script>

然后就是猎取iframe的window对象,由于只要拿到这个对象才向iframe中传东西

<template>
  <div class="act-form">
    <iframe :src="src" ref="iframe"></iframe>
  </div>
</template>

<script>

export default {
  data () {
    return {
      src: '你的src'
    }
  },
  mounted () {
    // 这里就拿到了iframe的对象
    console.log(this.$refs.iframe)
    // 这里就拿到了iframe的window对象
    console.log(this.$refs.iframe.contentWindow)
  }
}
</script>

3、vue怎样向iframe内传送信息?

经由过程postMessage,详细关于postMessage是什么,本身去google,

我的明白postMessage是有点类似于UDP协定,就像短信,是异步的,你发信息过去,然则没有返回值的,只能内部处置惩罚完成今后再经由过程postMessage向外部发送一个音讯,外部监听message

为了让postMessage像TCP,为了体验像同步的和完成多通讯互不滋扰,迥殊制订的message构造以下
{
  cmd: '敕令',
  params: {
    '键1': '值1',
    '键2': '值2'
  }
}

经由过程cmd来区分这条message的目标

详细代码以下

<template>
  <div class="act-form">
    <iframe :src="src" ref="iframe"></iframe>
    <div @click="sendMessage">向iframe发送信息</div>
  </div>
</template>

<script>

export default {
  data () {
    return {
      src: '你的src',
      iframeWin: {}
    }
  },
  methods: {
    sendMessage () {
      // 外部vue向iframe内部传数据
      this.iframeWin.postMessage({
        cmd: 'getFormJson',
        params: {}
      }, '*')
    },
  },
  mounted () {
    // 在外部vue的window上增加postMessage的监听,而且绑定处置惩罚函数handleMessage
    window.addEventListener('message', this.handleMessage)
    this.iframeWin = this.$refs.iframe.contentWindow
  },
  handleMessage (event) {
    // 依据上面制订的构造来剖析iframe内部发回来的数据
    const data = event.data
    switch (data.cmd) {
      case 'returnFormJson':
        // 营业逻辑
        break
      case 'returnHeight':
        // 营业逻辑
        break
    }
  }
}
</script>

4、iframe内怎样向外部vue发送信息?

如今经由过程点击“向iframe发送信息”这个按钮,从外部vue中已向iframe中发送了一条信息

{
  cmd: 'getFormJson',
  params: {}
}

那末iframe内部怎样处置惩罚这个信息呢?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>iframe Window</title>
    <style>
        body {
            background-color: #D53C2F;
            color: white;
        }
    </style>
</head>
<body>

    <h1>Hello there, i'm an iframe</h1>

    <script>
        // 向父vue页面发送信息
        window.parent.postMessage({
            cmd: 'returnHeight',
            params: {
              success: true,
              data: document.body.scrollHeight + 'px'
            }
        }, '*');

        // 接收父页面发来的信息
        window.addEventListener("message", function(event){
          var data = event.data;
          switch (data.cmd) {
            case 'getFormJson':
                // 处置惩罚营业逻辑
                break;
            }
        });
    </script>
</body>
</html>

至此内部的收发信息已处理了,外部的收发也已处理了,快去处理你的题目吧

在这里先直接给出我项目标源码

<template>
  <div class="act-form">
    <div class="nav">
      <img src="https://cxkccdn.oss-cn-shanghai.aliyuncs.com/lesai_img/icon_back_white.png" @click="back()">
      <div class="title">报名</div>
    </div>
    <div class="iframe-out">
      <iframe :src="src" ref="iframe" @load="iframeLoad"></iframe>
    </div>
    <div v-if="isLoaded" class="send-form"><div class="send" @click="sendMessage()">提交</div></div>
  </div>
</template>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="sass" rel="stylesheet/sass">
  @import "style.scss";
</style>

<script>
import { Toast, Indicator } from 'mint-ui'
import api from '@/utils/api'

export default {
  data () {
    return {
      src: '',
      iframeWin: null,
      isLoaded: false
    }
  },
  created () {
    let matchFamily = this.$store.state.matchFamily
    this.src = process.env.BASE_URL + '/matches/' + matchFamily.match.id + '/act/' + matchFamily.act.id + '/joinweb?token=' + this.$store.state.token
  },
  mounted () {
    window.addEventListener('message', this.handleMessage)
    this.iframeWin = this.$refs.iframe.contentWindow
    // 开启加载动画
    Indicator.open({
      text: '勤奋加载中...',
      spinnerType: 'triple-bounce'
    })
  },
  methods: {
    back () {
      this.$router.push('/actIntro')
    },
    sendMessage () {
      this.iframeWin.postMessage({
        cmd: 'getFormJson',
        params: {}
      }, '*')
    },
    iframeLoad () {
      // 封闭加载动画
      Indicator.close()
    },
    async handleMessage (event) {
      const data = event.data
      switch (data.cmd) {
        case 'returnFormJson':
          if (data.params.success) {
            // 挪用报名要领
            await this.enroll(data.params.data)
          } else {
            console.log('returnFormJson失利')
            console.log(data.params)
          }
          break
        case 'returnHeight':
          if (data.params.success) {
            this.$refs.iframe.height = data.params.data
            this.isLoaded = true
          }
          break
      }
    },
    async enroll (data) {
      let matchFamily = this.$store.state.matchFamily
      let result = await api.enroll(matchFamily.match.id, matchFamily.act.id, data)
      if (result.success) {
        if (result.data.status === 'no_pay') {
          // 更新缓存
          let resultMatch = await api.match(matchFamily.match.id, {})
          if (resultMatch.success) {
            this.$store.commit('SET_CURRENT_MATCH', resultMatch.data)
          }
          Toast({
            message: '报名胜利',
            position: 'bottom'
          })
          this.$router.push('/match/' + matchFamily.match.id + '/mdetail')
        } else {
          console.log('须要跳转到付出页面')
        }
      }
    }
  }
}
</script>

迎接人人来看看我的博客 https://www.windzh.com

    原文作者:Wind
    原文地址: https://segmentfault.com/a/1190000016258735
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞