vue中iframe使用以及结合postMessage实现跨域通信

Tertia ·
更新时间:2024-11-13
· 1124 次阅读

目录

使用场景

需求

iframe使用

基本使用

常用属性

iframe高度自适应

获取iframe的内容

同域下获取父级/子级内容

iframe跨域

postMessage通信

在vue中使用

使用场景 需求

在一个H5项目的页面中以url的方式嵌入另一个项目的页面。(不得不使用iframe)

而为了兼容移动端api(封装的一个移动端api,iframe内嵌页面不生效),需要实现父子页面的通信 (使用postMessage)。

iframe使用 基本使用

直接在页面嵌套iframe标签指定src即可使用iframe。

<iframe src="xxx.html"></iframe> 常用属性

frameborder:是否显示边框,1(yes),0(no)

height:框架作为一个普通元素的高度。

width:框架作为一个普通元素的宽度。

name:框架的名称,window.frames[name]时专用的属性。

scrolling:框架的是否滚动。yes,no,auto。

src:内框架的地址,可以使页面地址,也可以是图片的地址。

sandbox:对iframe进行一些列限制,IE10+支持

更多属性访问: 这里

iframe高度自适应 let ifr = document.getElementById('ifr') const deviceHeight = document.documentElement.clientHeight; ifr.style.height = (Number(deviceHeight)) + 'px'; 

vue中需要在mounted()中进行高度初始化

获取iframe的内容

通过两个主要的API:contentWindow 和 contentDocument

iframe.contentWindow,获取iframe的window对象

iframe.contentDocument,获取iframe的document对象

var iframe = document.getElementById("iframe1"); var iwindow = iframe.contentWindow; var idoc = iwindow.document; console.log("window",iwindow);    //获取iframe的window对象 console.log("document",idoc);    //获取iframe的document console.log("html",idoc.documentElement);    //获取iframe的html console.log("head",idoc.head);    //获取head console.log("body",idoc.body);    //获取body

通过Name属性,通过window提供的frames获取

<iframe src ="xxx.html" id="ifr1" name="ifr1" scrolling="yes">     <p>Your browser does not support iframes.</p> </iframe> <script type="text/javascript">     console.log(window.frames['ifr1'].window);     console.dir(document.getElementById("ifr1").contentWindow); </script>

window.frames['ifr1'] 返回的就是window对象,即 window.frames['ifr1']===window

同域下获取父级/子级内容

window.parent:获取上一级的window对象,如果还是iframe则是该iframe的window对象

window.top:获取最顶级容器的window对象

iframe跨域

以下形式的跨域,可以使用iframe进行解决。某一方使用iframe嵌套在另一方。

比如:http://www.foo.com/a.html 和 http://script.foo.com/b.html

两个文件中分别加上 document.domain = 'foo.com',指定相同的主域,然后,两个文档就可以进行交互。

//b.html是以iframe的形式嵌套在a.html中 //www.foo.com上的a.html document.domain = 'foo.com'; var ifr = document.createElement('iframe'); ifr.src = 'http://script.foo.com/b.html'; ifr.style.display = 'none'; document.body.appendChild(ifr); ifr.onload = function(){     var doc = ifr.contentDocument || ifr.contentWindow.document;     // 在这里操纵b.html     alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue); }; //script.foo.com上的b.html document.domain = 'foo.com';

默认情况下 document.domain 是指 window.location.hostname 。可以手动更改,但是最多只能设置为主域名。 通常,主域名就是指不带www的hostname, 比如: foo.com , baidu.com 。

如果,带上www或者其他的前缀,就是二级域名或者多级域名。通过上述设置,相同的domain之后,就可以进行同域的相关操作。

如果设置的iframe的域名和 top.window 的域名完全不同。则可以使用postMessage()进行通信

postMessage通信

window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(443为https的默认值),以及主机 (两个页面的模数 Document.domain设置为相同的值) 时,这两个脚本才能相互通信。window.postMessage() 方法提供了一种受控机制来规避此限制,只要正确的使用,这种方法就很安全。

具体使用方式参考:window.postMessage

<iframe src="http://xxx.com" name="sendMessage"></iframe>

父页面向子页面传递信息:

// 父页面js let ifr = window.frames['sendMessage']; // 向子页面发送message ifr.postmessage('give u a message', "http://xxx.com"); // xxx.com页面js // 监听父页面传来的信息 window.addEventListener('message', receiver, false); function receiver(e) {     if (e.origin == 'http://xxx.com') {         if (e.data == 'give u a message') {             e.source.postMessage('received', e.origin);  // 向原网页返回信息         } else {             alert(e.data);         }     } } 在vue中使用 <iframe :src="src" ref="iframe" frameborder="0"></iframe>

1.要将获取到iframe的contentWindow属性放到mounted这个钩子函数中。

mounted() {     this.iframeWin = this.$refs.iframe.contentWindow; }

2.子页面向父页面传值

父页面代码:

// 父页面监听子页面传来的信息 mounted() {     window.addEventListener('message', this.handleMessage);     this.iframeWin = this.$refs.iframe.contentWindow; }, methods: {     handleMessage (event) {         const data = event.data.data         if(data.info === "success"){             alert(data.data)         }     } }

子页面代码:

sendMessage() {     // 向父页面发送信息     window.parent.postMessage({         data: {             info:"success",             data:"我是子页面的test!"         }     }, '*'); }

3.父页面向子页面传递信息同理

sendMessage () {     // 向子页面传数据,需要注意这里没有parent     this.iframeWin.postMessage({         info: 'success',         data: "我是来自父页面的data!"     }, '*') }

注意父向子传递信息的时候,要等子页面加载完成后,再进行通信

以上为个人经验,希望能给大家一个参考,也希望大家多多支持软件开发网。



VUE 跨域 通信 postmessage iframe

需要 登录 后方可回复, 如果你还没有账号请 注册新账号