看完必会的JSONP

前端之家收集整理的这篇文章主要介绍了看完必会的JSONP前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

导读

  为了弥补AJAX无法跨域的问题,JSONP应运而生。不过JSONP并不是唯一跨域的技术,更新的有CORS技术。

简介

  JSONP是JSON with padding(填充式JSON或参数式JSON)的简写,是应用JSON的一种新方法。JSONP看起来和JSON差不多,只不过是被包含在函数调用中的JSON,就像下面这样。callback({ "name": "real"})。下面分别来谈谈JSON和JSONP。

JSON

JSON的优点

  • JSON是一种数据格式。
  • 基于纯文本,跨平台不是问题。
  • JavaScript原生支持。JSON是JavaScript的一个严格的子集,利用了JavaScript中的一些模式(对象、数组等)来表示结构化数据。
  • 经过合理的排版后可读性较强,XML过于繁琐、冗长。
  • 容易编写和解析(JSON.stringify、JSON.parse),前提是要知道格式。

JSON数据的规则

  JSON的语法可以表示为以下三种类型的值。
  
1、简单值:字符串,数值,布尔值,null。但不支持undefined。如:5,”hello”,false。值得注意的是:JSON字符串必须使用双引号(单引号会导致语法错误
2、对象:”{}/Object”。对象是一种复杂数据类型。是一组无序的键值对。而每个键值对中的值可以使简单值(字符串),也可以是复杂数据类型(数组,对象)。

{
  "name": "real","age": 20,"friends": ["Laki","Sonny"] }

3、数组: “Array”。数组也是一种复杂数据类型,表示有序的值列表。其中数组中的值可以是简单数据类型(字符串),也可以复杂数据类型(数组、对象)。

[
  {
    "name": "Laki","age": "21" },{
    "name": "Sonny","age": "22","friens": [ "real","Laki" ] }
]

  对于日期类型:
  

var day = {
  date: new Date( 2016,10,2 )
}
var jsonDay = JSON.stringify( day );// 转换为JSON格式
/* 解析 */
var day2 = JSON.parse( jsonDay,function ( key,value) {
  if ( key === "date" ) {
    return new Date( value );
  } else {
    return value;
  }
})

  是的,JSON.stringify()有三个参数,JSON.parse()有两个参数。只不过我们平常只用第一个。详细的可以参考其他资料。

JSONP

1、JSONP是为了解决跨域问题产生的,为了弥补AJAX的不足。AJAX请求跨域资源,Chrome下会报错:
  XMLHttpRequest cannot load http://api.douban.com/book/subjects?q=javascript&alt=json&max-results=1. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost’ is therefore not allowed access.。说的是服务器端没有设置允许的请求源。
后端头部信息加上Access-Control-Allow-Origin: *可以解决(CORS)。

2、但是对于img、ifame、script等,我们发现,在它们的src中引用其他域的资源的时候,是可以加载的(对于iframe,如果跨域,虽然可以加载,但是无法进行DOM操作,postMessage可以解决)。

3,JSONP正式基于上述的技术:

  • script标签
  • script的src加载其他跨域资源。
  • 在资源加载进来之前提前定义好一个函数,这个函数接受一个参数(数据),用这个函数来处理数据。

4,上述的函数就是我们常说的callback函数函数名随意),callback函数接受数据(通常是json),进行解析并处理。

/* 前台 */

<script> window.onload = function () { var oBtn1 = document.getElementById( 'btn1' ); oBtn1.onclick = function () { var oScript = document.createElement( 'script' ); oScript.src = 'http://test.com/abc.PHP?t=str&callback=fn'; document.body.appendChild( oScript ); } } function fn( data ) { alert( data ); } function fn1 (data) { alert(data); } </script>
/* 后台:http://test.com/abc.PHP */

<?PHP
  $t = isset($_GET['t']) ? $_GET['t'] : 'num';
  $callback = isset($_GET['callback']) ? $_GET['callback'] : 'fn1';

  $arr1 = array('111111','22222222','33333333','4444444','555555555555555555555');
  $arr2 = array('aaaaaaaaaaaa','bbbbbbbb','cccccccccccc','ddddddddd','eeeeeeeeeeee');

  if ($t == 'num') {
    $data = json_encode($arr1);
  } else {
    $data = json_encode($arr2);
  }

  echo $callback.'('.$data.');';

  可以看到,我们传递的callback指定了要处理数据的函数
  
5,如果我们不显示指明回调函数callback的话,那么会需要频繁的改动后台数据。
  比如对于上例,后台需要分别输出:
  echo 'fn('.$data.')';
  echo 'fn1('.$data.')';
  显然,这样是远远没有使用callback回调参数方便的。

Jquery中JSONP的写法  

  好吧,可能大家都用的jq,这里就里jq来写一个。以上述第4点给出的前端代码为例,其Jquery写法是:

$.ajax({ type: "get",url: "getData.PHP",dataType : 'jsonp',success: function ( data ) { console.log( data ); }
});

 对上面那么点代码,又有一些有趣的探讨。
 
Q:dataType : 'jsonp',不写行不行?
A:不写会返回一个函数。参数是后端返回的数据。比如jQuery20009081766414813617_1475405628630(["111111","22222222","33333333","4444444","555555555555555555555"]);这是上述例子返回的。

Q:可以手动指定回调函数吗?
A:正如上面一个问答,我们看到,回调函数是jQuery生成的一个函数。如果我们手动指定,只需要success: fn1。然后自己定义一个fn1函数即可。

Q:前端没指定callback,那么后端的$callback是什么?
A:估计很多伙伴没有思考过这个问题。是”fn1”吗?答案是:不是。因为我们在请求的时候,jQ内部给我们手动添加了一个参数callback=***。这是我从chrome中看到的参数:
  callback:jQuery200039165487775940955_1475409598758
  _:1475409598759
后面是时间参数,前面就不知道了。。所以我们在后端获取callback是可以获取到的。但是比方说改成callback2就不可以获取到了,那么,$callback = ‘fn1’。
  好了,关于jQuery中的jsonp暂时就介绍这么多,有机会再介绍。

应用实例(百度搜索

  模拟百度搜索
  

<!DOCTYPE HTML>
<html>
<head>
<Meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>标题文档</title>
<style> *{ margin: 0; padding: 0; } #q{ width: 300px;; height: 30px; padding: 5px; border: 1px solid #f90; font-size:16px; } #q:focus { /*outline:0;*/ border: 1px solid #f90; outline: 1px solid #f90; } #ul1 { display:none; border: 1px solid #f90; width:310px; } li a { display: block; width: 310px; height: 24px; padding: 5px 0; color: #666; text-decoration: none; } li a:hover { background: #f90; color: white; } </style>

</head>

<body>
  <input type="text" id="q" />
  <ul id="ul1">

  </ul>

<script> window.onload = function () { var oQ = document.getElementById( 'q' ); var oUl = document.getElementById( 'ul1' ); oQ.onkeyup = function () { if ( this.value !== '' ) { var oScript = document.createElement( 'script' ); /*以json形式返回数据,否则返回array类型*/ oScript.src = 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd='+ this.value +'&json=1&cb=customFunction&_'+ new Date().getTime(); document.body.appendChild( oScript ); } else { oUl.style.display = 'none'; } } } function customFunction (data) { console.log( data ); var html = '',oUl = document.getElementById( 'ul1' ); if ( data.s.length ) { //搜索结果存在,百度搜索搜索框值很多的时候,没有了结果。比如ddddddddddd... oUl.style.display = 'block'; for ( var i = 0,len = data.g.length; i < len; i++ ) { html += '<li><a href="https://www.baidu.com/s?ie=utf-8&wd='+ data.g[i].q +'">'+ data.g[i].q +'</a></li>'; } } oUl.innerHTML = html; } </script>
</body>
</html>

  关于对百度请求url。可参考我的另一篇文章http://www.jb51.cc/article/p-arswfmnn-od.html
  
  是不是和百度的一模一样呢。

小结

  1,大致讲了JSON数据格式。
  2,JSONP的原理。
  3,JSONP模拟的百度搜索
  4,给出了JS操作JSONP和JQ操作JSONP的例子。

参考

JavaScript高级程序设计,第三版。

猜你在找的Json相关文章