jQuery jsonp(转载)

来源:https://www.jianshu.com/p/1efe671832e0

其他文章:https://www.cnblogs.com/chiangchou/p/jsonp.html

jsonp本身是专为跨域而诞生的。早期开发者面对跨域没什么好办法,突然有人想到,既然引入js文件是不受跨域限制的,可以随意跨域引入,那么,动态引入一个带有你想要的数据的js文件,不就实现了跨域了么?由此jsonp技术诞生。

注意,jsonp技术跟ajax没有任何关系,只不过jQuery带了一个坏的头,让人们误以为jsonp跟ajax有关。

原理

jsonp的原理简单说就是:

第一步,你的HTML中应当提前准备一个函数,比如叫ooo,大致如下,它只干一个事情,就是把json字符串转换为json对象:

function ooo(data) { return JSON.parse(data); } 

第二步,你在你的HTML中用js拼接字符串的方式拼接一个类似于<script src="http://外域.com/xxx.php?callback=ooo"></script>的script元素。这个http://外域.com/xxx.php?callback=ooo的内容如下:

ooo({"name": "张学友"})

然后你需要操作DOM,把上面的<script src="http://外域.com/xxx.php?callback=ooo"></script>插入到DOM中,这样浏览器就会把这个地址当做js文件载入,然后试图执行里面的js内容。

既然这个文件被当做js来插入DOM,那么里面所有代码都是js代码,这个ooo({"name": "张学友"})就是js代码,浏览器会找有没有一个叫ooo的函数,显然有,我们刚才不是定义了一个ooo函数么?所以浏览器找到了这个函数,之后就执行这函数。

最后,我们就得到了一个json对象,而这个对象就是来自于外域服务器。由此,跨域达成。

没错吧,从头到尾并没有ajax什么事。

可以看出,本域跟外域沟通的桥梁,是外域的一个php文件,接头暗号就是路径里的参数callback=ooo。也就是说,php文件要做的事情应该是:

获取callback参数的值,然后拼接一个字符串ooo({"name": "张学友"}),其中ooo来自callback参数的值,{"name": "张学友"}是从sql中查询到的结果。

用jQuery实现jsonp的好处

然后说说jQuery的实现。jq为了让使用者更省心,当然是做了很多自动化的工作,下面都可以一一看到。主要是:

1、你不用自己写类似这样的函数,因为jQuery已经帮你写了:

function ooo(data) { return JSON.parse(data); } 

2、你不用思考函数名用啥名,因为jQ会帮你瞎编一个函数名,通常长相是jQuery32108394227022163139_1498134481374一大串。

jQuery中怎么实现jsonp

通常三种办法:

第一种,$.ajax()方法

当引入http://外域.com/xxx.php?callback=ooo,php端必须让这个地址能打印出ooo({"name": "张学友"})这样的内容,函数名ooo必须跟下面的jsonpCallback的值一致。json内容可以任意。

JS:

$.ajax({
    url:'http://外域.com/xxx.php', dataType:"jsonp", jsonp: "callback", jsonpCallback:"ooo", success:function(data){ console.log(data); } }); 

这个例子里面,明确指定了jsonp: "callback"以及jsonpCallback:"ooo"。我们分别说一下:

jsonp: "callback"是设置路径里的参数名。你这里写callback,那么jQuery发送请求的时候路径里就用callback=

jsonpCallback:"ooo"是设置函数名。你这里写ooo,那么php必须返回ooo为函数名的内容。

这两者都可以省略,jsonp的值省略的话,缺省是callback。jsonpCallback的值省略的话,缺省是类似jsonp3731491014413739这样的'jsonp'加16位随机数。两者都省略的话,jQuery就会在路径后面接一个callback=jsonp3731491014413739这样的参数,那么,你的php就必须返回jsonp3731491014413739({"name": "张学友"})这样的字符串。说白了,你如果js端想少写几个字,打算省掉这两个参数,那么php端就多写一些代码,需要先获取$_GET['callback']的值,根据值拼接字符串,因此你就不可能写死函数名。

最佳实践是省掉这两个参数,不过你的php端就要对参数值做安全措施。

第二种,$.get()方法(作者推荐)

$.get()方法的基本用法是同域名抓数据,是真正的ajax原理。而高级用法就是抓jsonp数据。写法是:

$.get('http://外域.com/xxx.php', {各种数据}, function(data) { console.log(data); }, 'jsonp'); 

没有指定末尾的'jsonp'参数的时候,jQuery认为你想同域抓数据,会用xhr方法请求;只有加了参数,才认为你想抓jsonp数据。这一切由jQuery自动判断。

这个写法其实就是上面ajax写法的简化版,而且肯定设不了jsonp和jsonpCallback,所以你的php必须用类似echo $_GET['callback'].'({"name":"张学友"})';这样的写法。假如你的路径中本来就有callback参数,而且这个callback是干别的用的,那么你就没法用$.get()方法。因为你真正的请求路径会是:http://外域/xxx.php?callback=12345678&callback=jQuery321040155744415047234_1498133674752&_=1498133674753,看到了吧,两个callback参数,php只会认后一个,忽略前一个。

第三种:$.getJSON()方法

$.getJSON()方法跟$.get()方法类似,区别在于:

1、$.getJSON()的最后一个参数不用写,而$.get()方法的最后一个参数必须是'jsonp'。

2、$.getJSON()虽然省掉了最后一个参数,但这时候,你需要在路径中带上callback=?或者abc=?这样的字眼,这样jQuery会自动判断,既然你带上了参数,而且参数值是问号,那么jQuery就认为你想搞jsonp勾当,如果你不加任何参数,或者参数值不是问号,那么jQuery就认为你不想搞jsonp勾当,那么这时候$.getJSON()方法就全等于$.get(...,..., 'json')方法。

同样的,你如果用callback=?,那么你php里应该是echo $_GET['callback'].'({"a": "张学友"})';,如果你用abc=?,那么你php里得是echo $_GET['abc'].'({"a": "张学友"})';

$.getJSON('http://外域/xxx.php?abc=?', {各种数据}, function(data) { console.log(data); }); 

结论

要让我选最好用的一个,我选$.get()方法,因为$.get()方法的最后一个参数'jsonp'能显式声明这个请求是jsonp请求,再一个,$.getJSON()方法的url要加上callback=?这种字眼,显得繁琐。

$.ajax()方法不到必要时不要用,必须用的时候当然一定要用。



作者:microkof
链接:https://www.jianshu.com/p/1efe671832e0
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自www.cnblogs.com/hao-1234-1234/p/13177349.html