一、基础引导
(1)通过Ifram获取数据
通过Ifram的contentWindow获取index2.html数据
//index1
<iframe src="index2.html" id="myIframe"></iframe>
<script type="text/javascript">
var myIframe = document.getElementById('myIframe');
window.name = 'mainWindow';
myIframe.onload = function(){
console.log(myIframe.contentWindow.name); //iframWindow
}
</script>
//index2
<script type="text/javascript">
window.name = 'iframeWindow';
</script>
用Ifram加载一个页面,Ifram就是这个页面的窗口,可以通过.contentWindow获得这个窗口对象
父窗口访问子窗口通过.contentWindow,子窗口访问父窗口通过.parent
通过.parent来访问父窗口的name,此时window指向Index2
//index2
<script type="text/javascript">
<iframe src="index3.html" id="myIframe"></iframe>
window.name = 'iframeWindow';
var iframe = document.getElementById('myIframe');
iframe.onload = function(){
console.log(window.parent.name); //mainWindow
}
</script>
通过.parent.parent来访问父窗口的name,此时window指向Index3
//index3
<script type="text/javascript">
console.log(window.parent.parent.name); //mainWindow
</script>
index2相当于index的儿子,index3相当于index的孙子
(2)window共享性
window.name是具有共享性的,在同一个窗口不同的页面是可以共享的 ,而且可以随意的读写
//index1
<script type="text/javascript">
window.name="window";
location.href = "index2.html" //跳转到index2页面
</script>
//index2
<script type="text/javascript">
console.log(window.name) //window
</script>
这样是会报错的,两个页面的源不同就会受到同源策略的限制
//index1
<iframe src="http://....index2.html" id="myIframe"></iframe> //不同源的地址
<script type="text/javascript">
var myIframe = document.getElementById('myIframe');
myIframe.onload = function(){
console.log(myIframe.contentWindow.name);
}
</script>
iframe之间的window.name是共享的,而主页面获取不同源的frame页面window.name是不行的
二、跨域
(1)服务器中转跨域
同源策略只针对浏览器,服务器之间没有跨域限制
在同源的服务器里面写一个程序,让服务器请求不同源的数据(后端程序中转)
(2)domain跨域
先设置主页面和frame页面的基础域名,再通过frame窗口拿到AJAX请求的接口,再通过这个接口发起HTTP请求
//index1
document.domain = "xxx.com";
var iframe = document.createElement('iframe');
iframe.src = "http://test.xxx.com/index.html";
iframe.id = "myIframe";
iframe.style.display = "none";
iframe.onload = function(){
var $$ = document.getElementById('myIframe').contentWindow.$;
$$.post('http://test.xxx.com/get.php',{status:1},function(data){})
}
document.body.appendChild(iframe);
//index2
document.domain="xxx.com"
封装
var ajaxDomain =(function(){
function createIframe(frameId, frameUrl){
var frame = document.createElement('iframe');
frame.src = frameUrl;
frame.id = frameId;
frame.style.display = 'none';
return frame;
}
return function(opt){
document.domain = opt.basicDomain;
var frame = createIframe(opt.frameId,opt.frameUrl);
frame.onload = function(){
var $$ = document.getElementById(opt.frameId).contentWindow.$;
$$.ajax({
url:opt.url,
type:opt.type,
data:opt.data,
success:opt.success,
error:opt.error
})
}
document.body.appendChild(iframe);
}
})();
//调用
ajaxDomain({
basicDomain:'xxx.com',
frameUrl:'http://test.xxx.com/index.html',
url:'http://test.xxx.com/get.php',
type:'POST',
data:{
status:1
},
success:function(data){},
error:function(data){}
})
(3)window.name跨域
先让iframe中的页面程序保存window.name,然后跳转与父级别窗口同源的另一个页面,父级页面可以从当前的iframe拿到该页面的window.name
window.name的特点:
- 每个浏览器窗口都有一个全局变量window(包含iframe的contentWindow)
- 每个window对象都有一个name属性(注意:一个窗口只有一个name属性)
- 该窗口被关闭前,所有页面共享一个name属性并拥有读写权限
- 无论该窗口在被关闭前,载入什么页面,都不会改变name值
- 存储约为2M字符串
- 如果父级窗口地址源和iframe地址源不同,父级无法通过ifram.contentWindow.name获取值,但iframe内部不受该规则限制
//index1
var flag = false;
var iframe = document.createElement('iframe');
var getDatas = function(){
if(flag){
var data = iframe.contentWindow.name;
}else{
flag = true;
setTimeOut(function(){
iframe.contentWindow.loaction ='index2.html';//加载完后,就会再次触发onlaod事件,此代码块执行两次
},500); // 延迟500毫妙为AJAX请求争取时间
}
}
iframe.src = 'http://xxx.com/index.html';
if(iframe.attachEvent){
iframe.attachEvent('onload',getDatas);
}else{
iframe.onload = getDatas;
}
document.body.appendChild(iframe);
//index2
空 与index1同源 //iframe不管怎么跳转都可以获得window.name,这里跳转到与index1同源的地址
//index3
$.post{'http:xxx.com/get_courses.php',{
status:1
}, function(data){
window.name = JSON.stringify(data);
}}
主页面只能获取同源的frame页面的window.name,而frame之间的window.name是共享的,不受同源策略影响。那么可以通过把frame跳转的地址设置为与主页面同源的地址,即可实现window.name跨域请求
(4)Postmessage跨域
不常用的原因:
- 伪造数据端漏洞
- xss攻击
- 兼容性问题
变量参数: otherWindow.postMessage(message,targetOrigin)
otherWindow: 接收方的引用
message: 要发送到接受方的数据
targetOrigin: 接收方的源,还有必需要有监听的message事件
//index1
<iframe src="http://text.xxx.com/index.html" id="iframe"></iframe>
<script type="text/javascript>
window.onmessage = function(e){ //等待接收数据
var e = e || window.event;
console.log(JSON.parse(e.data));
}
//index2
$.post('http://test.xxx.com/get.php',{status:1},function(data){
window.name= JSON.stringify(data); //只能传字符串
window.parent.postMessage(JSON.stringIfy(data),'http://index1.html'); //发送数据和接收地址源
})
(5)Hash跨域
基本原理: 利用url的hash值#xxx来传递数据
基础工具: location.hash
//index1
<button id= "btn">获取HASH</button>
<iframe src="http://test.xxx.com/index2.html#getCourses" id='cc' />
<script type="text/javascript">
var oBtn = document.getElementById('btn');
oBtn.onclick = function(){
console.log(JSON.parse(decodeURI(location.hash.substring(1))))
}
</script>
//index2
<iframe src="http://test2.xxx.com/index3.html" id="iframe" ></iframe>
var hash = location.hash.substring(1),
iframe = document.getElementById('iframe');
switch(hash){
case 'getCourses':
$.post('htttp://xxx.com/get.php',{},function(){
var str = JSON.stringify(data);
iframe.src = "http://xxx.com/index3.html#"+str;
})
}
//index3 与index1 同源
setTimeout(function(){
parent.parent.location.hash = self.location.hash.substring(1);
},300)
(6)Cors跨域
“跨域资源共享”(Cross-origin resource sharing)
Access-Control-Allow-Origin
- 任意域名:
header("Access-Control-Allow-Origin;*");
- 单域名:
header("Access-Control-Allow-Origin;http://test2.jsplusplus.com");
- 多域名:
$allowed_origins = array('http://test2.jsplusplus.com','http://test3.jsplusplus.com');
header("Access-Control-Allow-Origin:".$allowed_origins);
Access-Control-Request-Methods
通知服务器在真正的请求中会采用哪种HTTP方法
header("Access-Control-Request-Methods;GET,POST");
在服务端设置请求跨域的头信息header("Access-Control-Allow-Origin;xxx)、header(“Access-Control-Request-Methods;GET,POST”)的方式叫Cors跨域