但是,如果不同源,就会报错:

DOMException: Blocked a frame with origin "http://localhost:8085" from accessing a cross-origin frame.

网上搜索到的办理办法是,利用 iframe 的 contentWindow.postMessage 方法通报数据给子页面。
但是有一个问题,什么时候调用能得到真正的 iframe 工具呢?

组件通报数据的机遇

经由反复测试,笔者创造:如果直接在 Vue 父组件的 created 方法中向 iframe 通报数据,此时 iframe 由于并没有被访问,导致无法传数据,无论是通过 id 还是 $refs 都不能获取到这个 iframe 工具。

html的iframVue 中嵌入 iframe 并进行双向通讯的完全流程 GraphQL

看这段网上搜到的通用方法:

<el-dialog :visible="showIFrame" :close-on-click-modal="false" @close="closeSelf" title="弹框配置" > <iframe id="myFrame" ref="myframe" src="http://localhost:8085/myIFrame.html" frameborder="0" scrolling="auto" marginheight="0" marginwidth="0" width="100%" height="726px;"> </iframe> </el-dialog>

此时,如果在 created 方法中通报数据:

created() { // 监听子组件的关闭事宜 window.addEventListener('message', () => { this.closeSelf(); }, false); // 向子组件通报初始化数据 this.$refs.myframe.contentWindow.postMessage(data, ''); // 取到的是 undefined const iframe = document.getElementById('myframe'); // 为 null iframe.contentWindow.postMessage(data,""); },

代码运行会报两种缺点。

缺点一,$refs 中没有该组件:

缺点一

缺点二,id 为 myframe 的元素为 null:

缺点二

办理办法:在 iframe 的 load 事宜中向子页面通报数据,上面两种用法就不会报错了。

完全流程

父组件的 created 中监听子组件,调用关闭逻辑;同时,为 iframe 供应一个 @load="loaded" 事宜,在该事宜中调用 postMessage 向子组件发送初始化数据。

首先,弹框 Vue 组件 PopupIframe.vue 代码如下:

<template> <div id="app"> <el-dialog :visible="showIFrame" :close-on-click-modal="false" @close="closeSelf" title="Ifram配置"> <iframe v-show="src!==''" id="myframe" @load="loaded" ref="myframe" :src="src" frameborder="0" scrolling="auto" marginheight="0" marginwidth="0" width="100%" height="726px;"></iframe> </el-dialog> </div></template><script>export default { name: 'PopupIframe', props: ['showIFrame'], data() { return { src: '', data: { }, }; }, created() { // 设置 src this.src = 'http://localhost:8087/myIfram.html"; // 监听子组件的关闭事宜 window.addEventListener('message', () => { this.closeSelf(); }, false); }, methods: { loaded() { // 只有在 iframe 加载时通报数据给子组件,$refs 才是非空的 this.$refs.myframe.contentWindow.postMessage({ type: 'myData', data: this.data, }, ''); }, closeSelf() { // 关闭当前弹框 this.$emit('closeIframe'); }, },};</script>

第二步,iframe 子页面添加监听数据的方法:

window.addEventListener('message', (e) => { console.log(e.data); if (e.data.type === 'myData') { // TODO 利用父组件通报的初始化数据 }});

第三步,iframe 的页面的关闭按钮向父组件发送,关照关闭:

window.parent.postMessage('close', '');

PopupIframe.vue 被其他组件引用就可以了。

postMessage 数据类型

测试创造,this.$refs.myframe.contentWindow.postMessage 向 iframe 子组件发送数据后,子组件收到的数据除了第一步定义的数据外,还有其他数据,它的监听方法里面会实行两次:

postMessage 的内容

这解释,框架也向子组件发送了一些数据,类型为打包的告警数据。

因此,父组件通报数据时,也可以按照这个格式添加一个 type 标识我们的数据,前面第二步操作中,子组件利用时再根据它处理自己须要的数据。

总结:本文的核心知识点是 iframe 的 load 事宜,要想顺利通报数据给 iframe ,必须在这里调用才能得到 iframe 工具。