js 跨域复习 window.name | window.domain | iframe | Jsonp
引起跨域的原因:
浏览器的同源策略,但是当你要发送请求的时候,出于安全性问题,浏览器有严格的要求,必须协议,域名,端口都相同,这个就是同源策略。
影响:a通过js脚本向b发送ajax请求,不同源就会报错
不受影响:script标签,img标签等外部资源引用,重定向,表单提交都不受影响
****iframe遇到的跨域问题****
情况一、假设有a.com/main.html ; a.com/b.html
这种情况是涉及不到跨域的
main.html代码:
<html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div class="box"> <iframe id="if" src="b.html" frameborder="0"></iframe> </div> <script> //获取b的数据 var bdoc = window.frames[0].document; //通过bdoc做操作 </script> </body> </html>
b.html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <input id="message" type="text" /> <script> //获取父窗docuemnt var pdoc = parent.document; </script> </body> </html>
情况二、假设有a.com/main.html ; b.a.com/b.html 此时主域相同子域不同
只需要在两个页面同时显式的设置docuement.domian = “a.com”即可
情况三、主域不同 假设有页面 a.com/main.html ; a.com/blank.html ; b.com/b.html
此时可以利用window.name实现消息传递,具体做法如下:
b.html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <input id="message" type="text" /> <script> window.name = "我是要传递的消息"; </script> </body> </html>
a.html代码:
<html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div class="box"> <iframe id="if" src="b.com/b.html" frameborder="0"></iframe> </div> <script> var fr = document.getElementById('if'), state = 0;; if(window.VBArray){//兼容ie fr.onreadystatechange = function(){ if(this.readyState == 'complete'){ if(state == 1){ // 获取数据 data = fr.contentWindow.name; }else{ state = 1; // 重置iframe窗口的src保证同源 fr.src = 'a.com/blank.html'; } } } }else{ fr.addEventListener('onload',function(){ if(state == 1){ // 获取数据 data = fr.contentWindow.name; }else{ state = 1; // 重置iframe窗口的src保证同源 fr.src = 'a.com/blank.html'; } },false); } </script> </body> </html>
注意:window.name最大存储2M,只能存储字符串格式。由于此方法会重新加载空页面作为iframe的源,所以只适用于隐藏iframe的情况
****还有一种方式通过document.hash****
由父窗口修改子窗口的src添加hash,hash就是要传递的数据,修改hash不会导致页面刷新,子窗口通过一个定时器,定时检测hash是否变化,从而获取父窗口给的数据。
*****Jsonp跨域****
jsonp跨域原理:假设有a.com/a.html ;
,原理:动态创建script标签,利用script标签src不受同源策略影响
在页面定义处理数据的函数,参数就是要处理的数据,有后台返回一段js代码,这段代码必须调用a重定义的函数,将返回数据放在参数里
a.com/a.html代码:
funciton dealData(data){
//处理数据
}
var script = document.createElement("script"); script.src = "https://b.com/ask?data=1&callback=dealData"; document.body.insertBefore(script, document.body.firstChild);
此时后台返回的不是一般意义上的数据,而是一段script代码,这段代码调用我们的回调函数
由于是通过src来发出请求的,所以jsonp只能是get请求
****利用h5的api postMessage跨域****
假设有a.com/main.html ; b.a.com/b.html
这种方法一方通过postMessage向另一方发送消息,另一方通过onmessage事件获取到消息
postMessage(发送消息内容,发送目的地)
onmessage事件通过event.data获取消息
详细语法可以参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage
a.com/main.html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> .box{width:800px;height:400px;background:#ccc;} </style> </head> <body> <div class="box"> <iframe id="if" src="message.html" frameborder="0"></iframe> </div> <script> window.onload = function(){ window.frames[0].postMessage('parent','http://b.com/b.html'); } window.addEventListener('message',function(e){ var color=e.data; console.log(color) },false); </script> </body> </html>
b.html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <input id="message" type="text" /> <script> document.getElementById('message').value=111; window.addEventListener('message',function(e){ alert(1) console.log(e.data); document.getElementById('message').value=e.data; window.parent.postMessage(e.data,'*'); },false); </script> </body> </html>
****利用Cors跨域,这个方式需要后台配合设置header****