• vue内嵌iframe跨域通信


    1、Vue组件中如何引入iframe

    2、vue如何获取iframe对象以及iframe内的window对象?

    3、vue如何向iframe内传送信息?

    4、iframe内如何向外部vue发送信息?

    一、Vue组件中如何引入iframe?

    直接通过添加iframe标签,src属性绑定data中的src,第一步引入就完成了

    1. <template>
    2. <div class="act-form">
    3. <iframe :src="src">iframe>
    4. div>
    5. template>
    6. <script>
    7. export default {
    8. data () {
    9. return {
    10. src: '你的src'
    11. }
    12. }
    13. }
    14. script>

    二、vue如何获取iframe对象以及iframe内的window对象?

    获取iframe的window对象,因为只有拿到这个对象才能向iframe中传值

    1. <template>
    2. <div class="act-form">
    3. <iframe :src="src" ref="iframe">iframe>
    4. div>
    5. template>
    6. <script>
    7. export default {
    8. data () {
    9. return {
    10. src: '你的src'
    11. }
    12. },
    13. mounted () {
    14. // 这里就拿到了iframe的对象
    15. console.log(this.$refs.iframe)
    16. // 这里就拿到了iframe的window对象
    17. console.log(this.$refs.iframe.contentWindow)
    18. }
    19. }
    20. script>

    三、vue如何向iframe内传送信息?

    通过postMessage,具体关于postMessage是什么,自己去google,
     
    我的理解postMessage是有点类似于UDP协议,就像短信,是异步的,你发信息过去,但是没有返回值的,只能内部处理完成以后再通过postMessage向外部发送一个消息,外部监听message
     
    为了让postMessage像TCP,为了体验像同步的和实现多通信互不干扰,特别制定的message结构如下

    1. {
    2. cmd: '命令',
    3. params: {
    4. '键1': '值1',
    5. '键2': '值2'
    6. }
    7. }

     通过cmd来区别这条message的目的

    具体代码如下

    1. <template>
    2. <div class="act-form">
    3. <iframe :src="src" ref="iframe">iframe>
    4. <div @click="sendMessage">向iframe发送信息div>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. data () {
    10. return {
    11. src: '你的src',
    12. iframeWin: {}
    13. }
    14. },
    15. methods: {
    16. sendMessage () {
    17. // 外部vue向iframe内部传数据
    18. this.iframeWin.postMessage({
    19. cmd: 'getFormJson',
    20. params: {}
    21. }, '*')
    22. },
    23. },
    24. mounted () {
    25. // 在外部vue的window上添加postMessage的监听,并且绑定处理函数handleMessage
    26. window.addEventListener('message', this.handleMessage)
    27. this.iframeWin = this.$refs.iframe.contentWindow
    28. },
    29. handleMessage (event) {
    30. // 根据上面制定的结构来解析iframe内部发回来的数据
    31. const data = event.data
    32. switch (data.cmd) {
    33. case 'returnFormJson':
    34. // 业务逻辑
    35. break
    36. case 'returnHeight':
    37. // 业务逻辑
    38. break
    39. }
    40. }
    41. }
    42. script>

    四、iframe内如何向外部vue发送信息?

    现在通过单击‘向iframe发送信息’这个按钮,从外部vue中已经向iframe中发送了一条信息

    1. {
    2. cmd: 'getFormJson',
    3. params: {}
    4. }

    那么iframe内部如何处理这个信息?

    1. html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="utf-8">
    5. <title>iframe Windowtitle>
    6. <style>
    7. body {
    8. background-color: #D53C2F;
    9. color: white;
    10. }
    11. style>
    12. head>
    13. <body>
    14. <h1>Hello there, i'm an iframeh1>
    15. <script>
    16. // 向父vue页面发送信息
    17. window.parent.postMessage({
    18. cmd: 'returnHeight',
    19. params: {
    20. success: true,
    21. data: document.body.scrollHeight + 'px'
    22. }
    23. }, '*');
    24. // 接受父页面发来的信息
    25. window.addEventListener("message", function(event){
    26. var data = event.data;
    27. switch (data.cmd) {
    28. case 'getFormJson':
    29. // 处理业务逻辑
    30. break;
    31. }
    32. });
    33. script>
    34. body>
    35. html>

    至此为止,内部的收发信息和外部的收发信息都已解决!

    下面是完整代码:

    1. <template>
    2. <div class="act-form">
    3. <div class="nav">
    4. <img src="https://cxkccdn.oss-cn-shanghai.aliyuncs.com/lesai_img/icon_back_white.png" @click="back()">
    5. <div class="title">报名div>
    6. div>
    7. <div class="iframe-out">
    8. <iframe :src="src" ref="iframe" @load="iframeLoad">iframe>
    9. div>
    10. <div v-if="isLoaded" class="send-form"><div class="send" @click="sendMessage()">提交div>div>
    11. div>
    12. template>
    13. <style lang="sass" rel="stylesheet/sass">
    14. @import "style.scss";
    15. style>
    16. <script>
    17. import { Toast, Indicator } from 'mint-ui'
    18. import api from '@/utils/api'
    19. export default {
    20. data () {
    21. return {
    22. src: '',
    23. iframeWin: null,
    24. isLoaded: false
    25. }
    26. },
    27. created () {
    28. let matchFamily = this.$store.state.matchFamily
    29. this.src = process.env.BASE_URL + '/matches/' + matchFamily.match.id + '/act/' + matchFamily.act.id + '/joinweb?token=' + this.$store.state.token
    30. },
    31. mounted () {
    32. window.addEventListener('message', this.handleMessage)
    33. this.iframeWin = this.$refs.iframe.contentWindow
    34. // 开启加载动画
    35. Indicator.open({
    36. text: '努力加载中...',
    37. spinnerType: 'triple-bounce'
    38. })
    39. },
    40. methods: {
    41. back () {
    42. this.$router.push('/actIntro')
    43. },
    44. sendMessage () {
    45. this.iframeWin.postMessage({
    46. cmd: 'getFormJson',
    47. params: {}
    48. }, '*')
    49. },
    50. iframeLoad () {
    51. // 关闭加载动画
    52. Indicator.close()
    53. },
    54. async handleMessage (event) {
    55. const data = event.data
    56. switch (data.cmd) {
    57. case 'returnFormJson':
    58. if (data.params.success) {
    59. // 调用报名方法
    60. await this.enroll(data.params.data)
    61. } else {
    62. console.log('returnFormJson失败')
    63. console.log(data.params)
    64. }
    65. break
    66. case 'returnHeight':
    67. if (data.params.success) {
    68. this.$refs.iframe.height = data.params.data
    69. this.isLoaded = true
    70. }
    71. break
    72. }
    73. },
    74. async enroll (data) {
    75. let matchFamily = this.$store.state.matchFamily
    76. let result = await api.enroll(matchFamily.match.id, matchFamily.act.id, data)
    77. if (result.success) {
    78. if (result.data.status === 'no_pay') {
    79. // 更新缓存
    80. let resultMatch = await api.match(matchFamily.match.id, {})
    81. if (resultMatch.success) {
    82. this.$store.commit('SET_CURRENT_MATCH', resultMatch.data)
    83. }
    84. Toast({
    85. message: '报名成功',
    86. position: 'bottom'
    87. })
    88. this.$router.push('/match/' + matchFamily.match.id + '/mdetail')
    89. } else {
    90. console.log('需要跳转到支付页面')
    91. }
    92. }
    93. }
    94. }
    95. }
    96. script>

  • 相关阅读:
    进程的退出
    Git 命令大全
    基于SSM的概念可视化程序设计学习系统毕业设计源码021009
    Java实现二叉树两个节点最近公共祖先
    「PAT乙级真题解析」Basic Level 1005 继续(3n+1)猜想 (问题分析+完整步骤+伪代码描述+提交通过代码)
    C++ 类的声明笔记
    SLAM从入门到精通(用c++实现机器人运动控制)
    ASP.NET 系列:单元测试
    从PMP理论看华为销售项目运作与管理
    循环结构--do-while循环
  • 原文地址:https://blog.csdn.net/boundle_ss/article/details/128133210