关于Vue中使用iframe并进行数据通信

前言

记录一下关于在vue中嵌套多个iframe时,如何进行vue文件和iframe的数据通信,并通过src实现动态切换不同的iframe。

一、文件结构

1、router

const routes = [
  {
    path: '/',
	redirect: '/parent',
  },
  {
	path: '/parent',
	name: 'parent',
	component: parent,
  },
  {
	path: '/children',
	name: 'children',
	component: children,
  },
  {
	path: '/children2',
	name: 'children2',
	component: children2,
  },
]

2、parent.vue

<template>
  <div>
    <div class="title">
      <button @click="btn">提交</button>
      <button @click="change1">切换children1</button>
      <button @click="change2">切换children2</button>
      <div>{{ childrenInfo }}</div>
      <div>{{ save }}</div>
    </div>
    <div class="box" id="iframeBox">
      <!-- <iframe
        id="iframeId"
        src="http://192.168.1.8:8080/children"
        width="100%"
        height="100%"
        marginwidth="0"
        marginheight="0"
        frameborder="0"
      ></iframe> -->
    </div>
  </div>
</template>

<script>
export default {
  name: 'parent',
  data () {
    return {
      iframe: '',
      iframeBox: '',
      save: '',
      childrenInfo: '',
      preview: ''
    }
  },
  methods: {
    btn () {
      this.iframeBox = document.querySelector('#iframeBox')
      this.iframe = document.createElement('iframe')
      this.iframe.onload = () => {
        console.log('加载完成') // 这样每次都会触发
        this.iframe.contentWindow.postMessage({ payload: 'iframe参数' }, '*')
      }
      this.iframe.src = 'http://192.168.1.8:8080/children'
      this.iframeBox.appendChild(this.iframe)
    },
    change1 () {
      this.iframe.src = 'http://192.168.1.8:8080/children'
    },
    change2 () {
      this.iframe.src = 'http://192.168.1.8:8080/children2'
    }
  },
  mounted () {
    // 向iframe发送信息
    this.iframeBox = document.querySelector('#iframeBox')
    this.iframe = document.createElement('iframe')
    this.iframe.onload = () => {
      console.log('加载完成') // 这样每次都会触发
      this.iframe.contentWindow.postMessage({ payload: 'iframe参数' }, '*')
    }
    this.iframe.src = 'http://192.168.1.8:8080/children'
    this.iframeBox.appendChild(this.iframe)


    // 监听子页面想父页面的传参
    window.addEventListener('message', (event) => {
      // 此处执行事件
      console.log('监听到子页面的传参[eltabs页面][formdata数据监听 ]')
      if (event.data.typeAction === 'save') {
        this.save = event.data.typeAction
        this.childrenInfo = '这是iframe页面传递过来的参数'
      }
      if (event.data.typeAction === 'preview') {
        this.save = event.data.typeAction
        this.childrenInfo = '这是iframe【2】页面传递过来的参数'
      }
    })
  }

}
</script>

<style scoped>
.title {
  height: 100px;
  border: 1px solid red;
}
.box {
  width: 100%;
  border: 1px solid red;
}
</style>

3、children.vue

<template>
  <div class="iframe">
    <div>iframe页面</div>
    <div>parent页面传递的参数:{{ parentData }}</div>
    <button @click="btn">向parent文件传递参数</button>
  </div>
</template>

<script>
export default {
  name: 'parent',
  data () {
    return {
      parentData: ''
    }
  },
  methods: {
    btn () {
      window.parent.postMessage({ typeAction: 'save' }, '*')
    }
  },
  mounted () {
    // 监听父组件传递过来的参数
    window.addEventListener('message', (event) => {
      console.log(event);
      // 此处执行事件
      console.log(event.data, '监听到vue页面的传参[iframe页面][操作类型数据监听 ]')
      if (event.data.payload) {
        this.parentData = event.data.payload
      }
    })
  }
}
</script>

<style scoped>
.iframe {
  border: 2px solid blue;
}
</style>

4、children2.vue

<template>
  <div class="iframe">
    <div>iframe【2】页面</div>
    <div>parent页面传递的参数:{{ parentData }}</div>
    <button @click="btn">向parent文件传递参数</button>
  </div>
</template>

<script>
export default {
  name: 'parent',
  data () {
    return {
      parentData: ''
    }
  },
  methods: {
    btn () {
      window.parent.postMessage({ typeAction: 'preview' }, '*')
    }
  },
  mounted () {
    // 监听父组件传递过来的参数
    window.addEventListener('message', (event) => {
      console.log(event);
      // 此处执行事件
      console.log(event.data, '监听到vue页面的传参[iframe【2】页面]')
      if (event.data.payload) {
        this.parentData = event.data.payload
      }
    })
  }
}
</script>

<style scoped>
.iframe {
  border: 2px solid blue;
}
</style>

二、iframe使用的一些坑

1、iframe.onload不生效

一定要注意iframe绑定事件和加载时的顺序,先绑定事件再赋值src地址,才会每次都会触发onload。
另外,不要在<template>中写iframe,最好通过动态创建的方式。

2、iframe监听出现2次事件

{type: ‘webpackInvalid’, data: undefined}
或者
{type: ‘webpackOk’, data: undefined}

具体出现的原因不清楚。
但可以判断event.data.payload是否存在,来保存正确数据。payload是传递的参数对象

3、tabs标签页嵌套不同iframe情况

可以通过切换iframe.src来实现

三、小技巧

1、以上方法仍无法进行数据通信的解决方案

如果iframe仍然无法正常的通信,可以考虑用下本地缓存来传递数据,这个也是可以的,已验证。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值