去年,在给导师做项目时需要解决一个跨域问题,当时没弄过,就从网上找了资料给解决了,时至今日让我再提怎么做的,早已忘掉。再有就是以前听过jsonp,但是对此概念全然不知,只觉得跟json只差一个p。直到前几天带我的师傅跟我说了下jsonp,然后又自己查看了jsonp的原理后,才知道jsonp是怎么一回事。为了以后自己可以快速拾起这些知识,在这里粗略记录一下。
iframe跨域
1.遇到的问题
我们的页面A.html
A.html要嵌套B.html页面,而且被嵌套的B.html页面需要调用A.html的js方法
思想:
在a.html同一个域下创建一个c.html,就是利用c.html这个页面来作为b.html页面访问a.html页面js方法的桥梁
通过在a.html中嵌套b.html,然后在嵌套在a中的b.html页面中再(有点绕,仔细体会)动态创建一个iframe,把c.html页面嵌套进去,然后b.html便可以通过动态嵌套的c.html页面来调用a.html的js方法了。
随便画了张图,表示下嵌套的层次:
实现:
直接上代码比较清楚:(ip跟域名来说不是在同一个域下,所以可以用一台机子中ip127.0.0.1与localhost来模拟)
localhost:8080/test1/a.HTML代码
<html> <head> <title>无标题文档</title> </head> <body> <iframe src="http://127.0.0.1:8080/test2/b.html" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" name="myframe"></iframe> <script> function test(data) { alert("这个是a中的方法,参数:"+data); } </script> </body> </html>这段代码中嵌套了b.html页面,然后,我们的目的是点击b.html页面中按钮可以调用a.html页面中的test方法。
localhost:8080/test1/c.HTML代码 (c.html页面与a.html页面在同一个域中,实验中与a.html页面同一目录下了)
<html> <head> <Meta charset="utf-8"> <title></title> <script> window.onload = function(){ var text = window.location.href.split('=')[1] parent.parent.test(text); } </script> </head> <body> </body> </html>c.html页面中没有什么代码,就是为了b.html页面调用此页面的时候,帮助调用a.html中的方法。
c调用a的方法的时候用了 parent.parent.方法名来调用的,因为c是作为a底下两层嵌套。
127.0.0.1:8080/test2/b.HTML代码
<!doctype html> <html> <head> <Meta charset="utf-8"> <title>跨域测试</title> </head> <body> <ul> <li>测试</li> </ul> <input type="button" onclick="exec_iframe()" value="调用a页面方法"></input> <script> function exec_iframe(){ //此方法就是动态创建iframe,然后将c.html页面嵌套进来 var text = "abcddddddd"; if(typeof(exec_obj)=='undefined'){ exec_obj = document.createElement('iframe'); exec_obj.name = 'tmp_frame'; exec_obj.src = 'http://localhost:8080/test1/c.html?content='+text; exec_obj.style.display = 'none'; document.body.appendChild(exec_obj); }else{ exec_obj.src = 'http://localhost:8080/test1/c.html?content='+text; } } </script> </body> </html>当点击b中的按钮时,会调用方法exec_iframe(),然后动态将c页面嵌套进来,c页面初始化便会调用其页面中的js方法,便实现了调用a页面中的test方法。
----------------------------------------------------------------------------------------------------------------
总结下流程:
启动tomcat,访问a.html页面
b页面中的内容便加载进来了,在b.html中有文本以及一个按钮,然后点击按钮,去调用a.html中的方法,这个过程就是上面说的,在b中动态嵌入c页面,然后由c页面来调用a中的方法。(参数没有转码,没什么影响)
同理,如果想在a中调用b中的方法的话,那可以在b.html同目录下或者说同域下创建一个页面d,d中调用b中的方法(parent.window.myframe.方法名,此处的myframe是b在a页面中的iframe名称),当a也调用b中方法的时候,同样在页面中动态创建一个iframe来嵌套d页面。
jsonp简谈
以我自己的理解,jsonp不是什么协议,更不是什么数据格式,只是帮助获取外域数据的一种方法。
这种方法就是利用了浏览器对<script src ="http://.............." ></script>不采取“同源策略”的特点来实现数据获取的。
a.html页面中有段js
<script> function test() { alert("通过远程资源文件调用我啊"); } </script> <script src="http://xxxxx/remote.js"></script>
test();
那当a页面加载时会弹出弹框。
其实,这就是jsonp的依赖的原理,src指向的不止是一个js文件,同样可以是一个请求地址:
src="http://xxxx/xxxx/getcount?callback=test"(callback就是一个普通参数名,完全可以换成别的,只要跟后台约定好就ok了)
这样的话我们可以在后台方法getcount中拿到参数callback,这个callback参数是干嘛的呢,就是向后台说明你从后台拿到数据后,要用哪个方法来处理,也就是让后台给你返回像上面test()方法这样的东西。
给个完整例子就是:
<script> function dealcount(data) { alert("获取后台数据:"+data); //拿到数据,处理数据 } </script> <script src="http://xxxx/xxxx/getcount?callback=dealcount"></script></span>
当这个页面加载的时候便回去请求这个链接,后台拿到参数test,以及经过后台处理好的数据data,然后返回来 dealcount(data),那么这个是不是就跟remote.js中写个dealcount(data)一样了,就会执行自己页面上写的dealcount(data)方法了。
但是这个例子是个静态的,不能每次都是页面加载的时候来请求吧。要需要时再去请求,那就写个方法去动态生成script标签,然后动态加载到页面中吧。
function jsonpRequest(){ var url = "http://xxxx/xxxx/getcount?callback=dealcount";</span> //创建script标签,设置其属性 var script = document.createElement('script'); script.setAttribute('src',url); //把script标签加入head,此时调用开始 document.getElementsByTagName('head')[0].appendChild(script); }
jsonp在jquery中也可以使用ajax的方式,只要知道了这个jsonp是个什么东西,那么ajax中的使用也就是一看便明了 了。
如果有别的跨域以及这方面的知识,可以推荐给我,谢谢!
--------------------等回头看看自己,写的又傻又笨的时候,那么说明我成长了!