关于跨域和jsonp的一些理解(新手向)
非常惭愧,还记得2016年那人生中第一次面试,被问到有没用过ajax?你怎么解决跨域问题时,我回答没用过。。不知道的时候,面试官那一脸茫然,对于当时以为js只是做个轮播图,做点小动画的我来说,ajax、跨域什么的就如同一道难以逾越的高墙一般。。 在后来的实习中终于接触到并且运用起了ajax,跨域也解决过,不过是后端同事解决的(现在才知道那应该就是CORS了吧),所以jsonp到底是啥,每次搜索完看了一下就放弃了。 本文内容浅显,适合人群: 什么是跨域我的理解是,当用户对不同协议或不同端口或不同域名的资源进行访问时,就是跨域。 为什么会造成跨域罪魁祸首:同源策略 同源定义:即同一域,即相同协议&相同端口&相同域名&相同子域名 同源策略规定:XHR对象只能访问与包含它的页面位于同一域中的资源,有利于预防一些恶意行为。 怎么解决跨域解决办法有很多,CORS、iframe、h5新特性postMessage等,而比较简单的方法就是今天着重介绍的jsonp。 解决依据:尽管不能访问非本域的动态资源,但是类似js文件、样式、图片等静态资源是可以访问的!就是通过这个“漏洞”来解决跨域问题。用<script>标签中的src来写入跨域数据的url,这样就能绕过同源策略了。。“老师,他作弊!” 简单介绍jsonpJSONP,JSON with Padding的简写,这个全称对jsonp的理解还是有一定的帮助的。填充式JSON或者说是参数式JSON。JSONP的语法和JSON很像,简单来说就是在JSON外部用一个函数包裹着。JSONP基本语法如下: callback({ "name": "kwan","msg": "获取成功" }); JSONP两部分组成:回调函数和里面的数据。回调函数是当响应到来时,应该在页面中调用的函数,一般是在发送过去的请求中指定。 JSONP原理: 原理看千遍,一写又不会我想说这个JSONP我看了很多次,参考过不同的文章,原理都会背了,结果自己写一个出来,傻眼。。 网上有很多文章,良心一点的会配有些代码解释,然而对小白来说,要自己down个WAMP什么的服务器集成软件或者自己搭个服务器,再弄两个不同源的html才能进行模拟跨域,这真的。。。。好麻烦。。 终于,看到了一篇文章,一个通过调用api接口来模拟跨域请求数据的DEMO,实在感谢啊!这才是我所要的好吗!(链接在本文最后) JSONP跨域小实践你再怎么懂原理,再怎么会JSONP基本语法,不真正执行一下你其实还是懵逼。 下面展示的代码源于那篇文章,需求是输入歌名,点击搜索后,跨域请求API接口,返回数据后,显示专辑名在页面。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JSONP</title> </head> <body> <input type="text" id="song" name=""> <input type="button" id="song_search" value="歌曲搜索" name=""> <br /> <div style="width:200px;height:230px;background:pink" id="song_list"></div> <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript"> var searchJsonCallback=function(data){ //遍历查询结果 var alb_html=''; for(var i in data.list){ alb_html+='<span>专辑:</span><div style="color:black">'+data.list[0].albumname+'</div>'; } $("#song_list").html(alb_html); }; $("#song_search").on("click",function(){ var keyword=$("#song").val(); if(keyword==undefined||keyword==""){ alert("歌曲搜索不能为空"); return false; }else{ var url = "http://cgi.music.soso.com/fcgi-bin/fcg_search_xmldata.q?source=10&w="+keyword+"&perpage=1&ie=utf-8"; // 创建script标签,设置其属性 var script = document.createElement('script'); script.setAttribute('src',url); // 把script标签加入head,此时调用开始 document.getElementsByTagName('head')[0].appendChild(script); } }); </script> </body> </html> 下面是我对以上代码的一些文字解释: 1)点击按钮后动态插入跨域数据,然后由于此接口用searchJsonCallback({})来封装json格式数据,因此可看作是调用一个函数,同时把json数据作为参数传入 2)所以当动态插入script标签后,写好了的searchJsonCallback()函数将被调用,参数data就是json数据,然后通过遍历渲染到DOM上,完成整个跨域获取数据流程 总结步骤:触发click事件-动态插入带有API接口的script标签-根据回调函数名调用函数-遍历数据-渲染到页面 当JSONP遇上jQuery ajax注意了,千万不要认为用了jQuery ajax,就是通过它来实现跨域请求,其实只是因为它很好地封装了JSONP而已 用jQuery ajax原理和上面的是一样的,只不过我们不需要手动的插入script标签以及定义回调函数。jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。 于是对上面的代码进行修改,并且把请求数据改为每次显示5条: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JSONP2</title> </head> <body> <input type="text" id="song" name=""> <input type="button" id="song_search" value="歌曲搜索" name=""> <br /> <div style="width:200px;height:230px;background:pink" id="song_list"></div> <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.min.js"></script> <script type="text/javascript"> $("#song_search").on("click",function(){ var keyword=$("#song").val(); if(keyword==undefined||keyword==""){ alert("歌曲搜索不能为空"); return false; }else{ $.ajax({ url: 'http://cgi.music.soso.com/fcgi-bin/fcg_search_xmldata.q?source=10&w='+keyword+'&perpage=5&ie=utf-8',type: 'GET',dataType: 'jsonp',jsonp:'callback',jsonpCallback: 'searchJsonCallback',success:function(data){ //遍历查询结果 var alb_html=''; //创建一个变量用于DOM拼接 for(var i in data.list){ alb_html+='<p style="color:black">'+data.list[i].albumname+'</p>'; console.log(data.list[i].singername); } var name_html='<span>专辑:</span>'; var sum_html=name_html+alb_html; $("#song_list").html(sum_html); } }); } }); </script> </body> </html> 关于jsonp、jsonpCallback两个属性,部分解释一直没看懂,如下: jsonp: "callback", 直到有次看了下Network,懂了。其实就是拼接到url时想要显示的内容。 如上面情况,url则会变成"http://...&perpage=5&ie=utf-8&callback=searchJsonCallback&..." 所以简单来说, 注意:jsonp可以随便写,不写也行,反正默认是callback 但jsonpCallback必须是对应其返回数据的函数名,此API接口返回的数据外围用searchJsonCallback()包裹数据,因此只能是这个 其实上面这些例子更方便将理论用于实践,毕竟数据等都是现成的,跨域问题也是常见的开发问题,感觉就没必要大费周章才能进行模拟跨域(所以我上面说自己弄服务器那种方法略麻烦) 参考资料: 另一篇帮助理解的文章: 还有很多良心文章就不一一列举了,这次是首次将跨域理论落实到实践,觉得很过瘾所以就写下来了。排版不太好勿见怪。大神路过如有些其他看法可以在下面留言。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |