看了一些博客,进行了总结和实践
<iframe src="demo.html" height="300" width="500" name="demo" scrolling="auto" sandbox="allow-same-origin">iframe>
iframe框架中的页面与主页面之间的通信方式根据iframe中src属性是同域链接还是跨域链接,有明显不同的通信方式。
iframe.contentWindow, 获取iframe的window对象
iframe.contentDocument, 获取iframe的document对象
var iframe = document.getElementById("iframe1");
iframe.contentWindow.document.querySelector('#div1').innerHTML='div1'
在vue中获取 iframe的window对象,dom通过ref
this.$refs.iframe.contentWindow
结合Name属性,通过window提供的frames获取.
window.frames[‘ifr1’]返回的就是iframe的window对象,即
window.frames['ifr1']===window
window.frames['ifr1'] == document.getElementById("iframe1").contentWindow
之后可以访问iframe的dom和方法
iframename.window.document.XX
iframename.window.function
//iframe2.window.document.getElementById(‘div1’).innerHTML=‘update’
同理,在同域下,父页面可以获取子iframe的内容,那么子iframe同样也能操作父页面内容。在iframe中,可以通过在window上挂载的几个API进行获取.
window.parent 获取上一级的window对象,如果还是iframe则是该iframe的window对象
window.top 获取最顶级容器的window对象,即,就是你打开页面的文档
window.self 返回自身window的引用。可以理解 window===window.self
window.parent.document.XX
window.parent.function
## 跨域
### 子域不一样但主域一样
对于主域相同子域不同的两个页面,我们可以通过document.domain + iframe来解决跨域通信问题。
在两个不同子域下(某一方使用iframe嵌套在另一方),
即:http: //www.foo.com/a.html和http: //script.foo.com/b.html
两个文件中分别加上**document.domain = ‘foo.com’**,指定相同的主域,然后,两个文档就可以进行交互。
然后可以像同域一样操作iframe的内容
例子
```js
//b.html是以iframe的形式嵌套在a.html中
//www.foo.com上的a.html
document.domain = 'foo.com';
var ifr = document.createElement('iframe');//创建一个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';
利用 location 对象的 hash 值,通过它传递通信数据,设置 iframe的 src 后面多加个#data 字符串(data就是你要传递的数据), 监听 location.href 的变化即可获得上面的 data 信息。
例子
父页面
<template>
<div>
<button @click="butClick2">向子页面发送数据(hash)</button>
<iframe src="http://localhost:8081/#/"
frameborder="0"
height="300"
width="500"
scrolling="auto"
ref="myiframe"></iframe>
<p>{
{
data}}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '',
data: ''
}
},
methods: {
butClick2() {
//向url后面拼接了要传输的数据,这里我发送了lily
this.$refs.myiframe.src += '#lily'
}
},
mounted() {
//监听子页面的数据传输
window.addEventListener('hashchange', (e) => {
this.data = location.hash.substring(2)
})
}
}
</script>
子页面
{
{name}}
代理irframe
<template>
<div class="frame">
www
{
{
data}}
</div>
</template>
<script>
export default {
data(){
return{
data : ''
}
},
mounted() {
window.addEventListener('hashchange', (e) => {
this.data = location.hash.substring(10)
parent.parent.location.hash = this.data //改变父组件的哈希值
})
},
}
</script>
<style scoped>
</style>
如果你设置的iframe的域名和你top window的域名完全不同。 则可以使用CDM(cross document messaging)进行跨域消息的传递。
发送消息: 使用postmessage方法
接受消息: 监听message事件
该方法挂载到window对象上,即,使用window.postmessage()调用.
该方法接受两个参数:postMessage(message, targetOrigin):
message: 就是传递给iframe的内容, 通常是string,如果你想传object对象也可以。但不要直接传Object。 可以使用是JSON.stringify进行转化。这样能保证不会出bug。
targetOrigin: 接受你传递消息的域名,可以设置绝对路径,也可以设置"“或者”/"。 表示任意域名都行,"/"表示只能传递给同域域名。当然也可以用*.向所有窗口发送。
总结就是:
在发送页面使用window.postmessage(message,targetOrigin), 发送信息(此时的window为接收方的window)
在接收页面使用window.addEventListener(‘message’, (e)=>{ })
当targetOrigin接受到message消息之后,会触发message事件。 message提供的event对象上有3个重要的属性,data,origin,source.
event.source 发送消息窗口
event.origin:消息发向的窗口
event.data消息内容
source 可判断发送源url,进行过滤
父页面
<template>
<div>
<p>123</p>
<button @click="butClick">向子页面发送数据(postMessage)</button> <br>
<iframe src="http://localhost:8081/#/"
frameborder="0"
height="300"
width="500"
scrolling="auto"
ref="myiframe"></iframe>
<p>收到子页面的内容:{
{
message}}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '',
data: ''
}
},
methods: {
butClick() {
//通过postMessage向子页面发送数据
this.$refs.myiframe.contentWindow.postMessage({
type: 'pro',
project: '项目一'
}, '*');
},
},
mounted() {
//监听子页面发送数据
window.addEventListener('message', (e) => {
if (e.data.type == 'message') {
this.message = e.data.message
}
})
}
}
</script>
子页面
<template>
<div class="frame">
<p>这是iframe的内容</p>
<p>{
{
project}}</p>
<p>{
{
name}}</p>
<button @click="butClick">子页面向父页面发送信息</button><br>
<button @click="butClick2">子页面向父页面发送信息hash</button>
<iframe src="http://localhost:8080/#/ifproxy" frameborder="0" ref="iframe2" style="display:none"></iframe>
</div>
</template>
<script>
export default {
data() {
return {
project: {
},
name: ''
}
},
mounted() {
//监听父组件发送的数据
window.addEventListener('message', (e) => {
if (e.data.type == 'pro') {
this.project = e.data.project
}
});
},
methods: {
//向父组件发送数据
butClick() {
window.parent.postMessage({
type: 'message',
message: '哦'
}, 'http://localhost:8080/#/')
},
}
}
必要时记得移除监听
destroyed () {
// 移除监听
window.removeEventListener('message',function (event) {
iframe.style.height = event.data.height + 'px'
})
}