iframe子页面ajax报错,iframe跨域踩坑

前言

工做中,有些系统是利用的iframe。有一次忽然遇到了一个使人费解的跨域报错,没有发请求,却报了“Error:Blocked a frame with origin...from accessing a cross-origin frame”的跨域错误的问题,当时本身一脸懵(恕我无知)……原来是由于本身的一句window.parent.document.scrollTop,万万想不到,iframe之间的通讯也会存在跨域问题,赶忙去研究一下。javascript

一.iframe跨域

其实前言的本质,就是由于父、子窗口这两个页面不一样源,可是却想在iframe中获取父窗口的dom,形成了跨域问题。html

若非同源,会受到三种跨域限制:一是ajax请求限制;二是DOM没法得到;三是Cookie、LocalStorage 和 IndexDB 没法读取。java

本文主要讲第二点,不知足同源策略的两个网页是没法拿到对方的DOM的。ajax

这里须要特别说明的是:阮一峰老师在文章 浏览器同源政策及其规避方法里说到父窗口想获取子窗口的DOM,由于跨源致使报错。chrome

可是经我这边用chrome操做,并无报错,是能够获取到dom的,我大胆猜测多是chrome更新了安全策略吧。跨域

举个栗子:浏览器

父窗口

export default {

name: 'Parent',

data () {

return {

}

},

mounted( ) {

console.log('document.getElementById("iframe1").contentWindow.document',document.getElementById("iframe1").contentWindow.document);

console.log('document.getElementById("iframe2").contentWindow.document',document.getElementById("iframe2").contentWindow.document);

}

}

复制代码

同源子窗口

export default {

name: 'Child_Same',

data () {

return {

}

},

mounted() {

console.log('同源 window.parent.document',window.parent.document);

}

}

复制代码

跨域子窗口

export default {

name: 'Child_Diff',

data () {

return {

}

},

mounted() {

console.log('跨域 window.parent.document',window.parent.document);

}

}

复制代码

de1cb9aadbb53d5ce4c2f50b217508c6.png

父窗口获取子窗口的DOM在同源和跨域下均可以获取;而子窗口获取父窗口的DOM在跨域时会报错,同源能够获取到。安全

二.解决方法

targetWindow.postMessage(data,targetOrigin,transfer)

这是跨窗口发送消息的方法。bash

逐一解释一下参数:dom

targetWindow: 窗口的引用。能够是当前窗口window,也能够是一个窗口得到的其它窗口的引用,能够为:

Window.parent

HTMLIFrameElement.contentWindow

Window.open

Window.opener

Window.frames +索引值

data: 传递的消息

targetOrigin:接收消息的目标窗口的源(协议 + 域名 + 端口)。能够设为*,表示不限域名,可向全部窗口发送。

transfer : 可选参数

好的,那么如何接收发来的消息呢?

目标窗口对message事件进行监听,便可得到发送过来的消息

window.addEventListener("message", receiveMessage, false);

function receiveMessage(event)

{

// For Chrome, the origin property is in the event.originalEvent

// object.

// 这里不许确,chrome没有这个属性

// var origin = event.origin || event.originalEvent.origin;

var origin = event.origin

if (origin !== "http://example.org:8080")

return;

// ...

}

复制代码

因此前言子获取父窗口dom的问题能够这样解决:

//父窗口向iframe发消息

document.getElementById("iframe").contentWindow.postMessage({scrollTop:document.body.scrollTop},'http://172.18.12.109:8082');

复制代码

//iframe接收消息

window.addEventListener('message', (e)=>{

let origin = event.origin || event.originalEvent.origin;

if (origin !== 'http://172.18.12.109:8080') {

return;

}else {

console.log(e.data);

//{scrollTop: 0}

}

},false);

复制代码

再举一个工做中遇到的栗子:

在iframe中不一样源的子窗口页面间实现跳转

具体以下:

有一个系统,是由提供了整个页面导航栏的父窗口A和iframe嵌入的不一样源的子窗口组成的。不一样一级导航对应不一样模块,同一模块下能够经过路由进行页面跳转,而不一样模块只能经过url跳转。

如今要实现点击模块B中的一个按钮从B跳转到模块C的一个页面,可是不能新开窗口跳转,仍是要在父窗口里,由于要外部导航栏始终不变,只是内部页面跳转。

所以这里须要用到在子窗口B和父窗口A通讯,而后在A中打开C这个窗口。

与前言一样的,此处为父向子发送消息,子窗口接收消息。

示例代码以下:

外部父窗口

export default {

name: 'Parent',

data () {

return {

}

},

mounted( ) {

//目标父窗口接收子窗口发送的消息

window.addEventListener('message', (e)=>{

let origin = event.origin || event.originalEvent.origin;

if (origin !== 'http://172.18.12.109:8082') {

return;

}else {

//更换iframe的src,实现iframe页面跳转

document.getElementById("iframe1").src=e.data.link;

}

},false);

}

}

}

复制代码

内部跨域子窗口1

点击向父窗口发送消息

export default {

name: 'Child_Diff1',

data () {

return {

}

},

methods: {

onClick () {

let message = {type: 'open', link:'http://172.18.12.109:8082/#/Child_Diff2'};

//子窗口向父窗口发送消息,消息中包含咱们想跳转的连接

window.parent.postMessage(message,'http://172.18.12.109:8080');

}

}

}

复制代码

实现效果:

b322a2bb629994f567ae2f6394afe7b0.gif

所以,最终可实现: 点击跨域子窗口1的按钮,向父窗口发送消息,告诉父窗口要跳转的跨域子窗口2的连接,父窗口接收到消息后,更改iframe src的url,便可实现不用打开新页面,iframe子窗口的变化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值