标签:
在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。
http://localhost:23383/Home/Index这个页面想跨域请求http://www.jscrossdomain.com/home/index的数据,www.jscrossdomain.com是服务器(也就是本地要模拟从服务器请求数据):
服务器端代码:
public class HomeController : Controller { public ActionResult Index() { var fun = Request["callback"] != null ? Request["callback"].ToString() : "a"; string result = fun + "({\"name\":\"zhangsan\",\"date\":\"2015-4-30\"})"; return Content(result); } }
客户端(跨域请求端):
<!DOCTYPE html> <html> <head> <title>Index</title> <script src="../../Scripts/jquery-1.4.4.min.js" type="text/javascript"></script> <script type="text/javascript"> var result = null; window.onload = function () { var script = document.createElement("script"); script.type = "text/javascript"; script.src = "http://www.jscrossdomain.com/home/index?callback=callback"; var head = document.getElementsByTagName("head")[0]; head.insertBefore(script, head.firstChild); }; function callback(data) { alert("我是被自动调用的"); result = data; } function b_click() { alert(result.name + "|" + result.date); } </script> </head> <body> <div> <input type="button" value="click me!" onclick="b_click();" /> </div> </body> </html>
客户端页面加载完毕,弹框,点击button弹框显示跨域请求数据。
<!DOCTYPE html> <html> <head> <title>Index</title> <script src="../../Scripts/jquery-1.4.4.min.js" type="text/javascript"></script> <script type="text/javascript"> function b_click() { $.ajax({ async: false, url: "http://www.jscrossdomain.com/home/index", type: "GET", dataType: ‘jsonp‘, //jsonp的值自定义,如果使用jsoncallback,那么服务器端,要返回一个jsoncallback的值对应的对象. jsonp: ‘callback‘, //要传递的参数,没有传参时,也一定要写上 data: null, timeout: 5000, //返回Json类型 contentType: "application/json;utf-8", //服务器段返回的对象包含name,data属性. success: function (result) { alert(result.name + "|" + result.date); }, error: function (jqXHR, textStatus, errorThrown) { alert(textStatus); } }); } </script> </head> <body> <div> <input type="button" value="click me!" onclick="b_click();" /> </div> </body> </html>
浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。有一点需要说明,不同的框架之间(父子或同辈),是能够获取到彼此的window对象的,但蛋疼的是你却不能使用获取到的window对象的属性和方法(html5中的postMessage方法是一个例外,还有些浏览器比如ie6也可以使用top、parent等少数几个属性),总之,你可以当做是只能获取到一个几乎无用的window对象。比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的
这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。
不过如果你想在http://www.example.com/a.html 页面中通过ajax直接请求http://example.com/b.html 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了。
标签:
原文地址:http://www.cnblogs.com/yangyp/p/4469398.html