iframe的使用,同域和跨域问题

看了一些博客,进行了总结和实践

文章目录

  • iframe的使用
    • 同域的api
      • 父页面调用子页面
        • 通过iframe的dom元素
        • 通过iframe的name属性
      • 子页面调用父页面
      • 域名完全不一样
        • 利用hash实现双方通信(已实验略麻烦)
        • 利用postmessage实现双方通信(推荐)

iframe的使用

<iframe src="demo.html" height="300" width="500" name="demo" scrolling="auto" sandbox="allow-same-origin">iframe>
  1. src iframe页面地址,有同域跨域之分
  2. name iframe命名,可通过window.frames[xxx]被调用

iframe框架中的页面与主页面之间的通信方式根据iframe中src属性是同域链接还是跨域链接,有明显不同的通信方式。

同域的api

父页面调用子页面

通过iframe的dom元素

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

通过iframe的name属性

结合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';

域名完全不一样

利用hash实现双方通信(已实验略麻烦)

利用 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>

​ 子页面





​ 代理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>

利用postmessage实现双方通信(推荐)

如果你设置的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'
    })
  }

你可能感兴趣的:(前端,javascript)