当端口或者ip不同的时候,如果去请求数据是不能成功的,所以这个时候需要用到跨域来实现数据的请求。
HTML中有几种标签是具有跨域功能的,分别是:
- img标签
- link标签
- iframe标签
- script标签
下面说一下这几种标签的特点: - img的src如果写一个网址,就会返回HTML代码,但是它只能解析图片类型的数据
- link标签只能解析css代码
- iframe标签只能解析HTML代码
script标签只能解析js代码
当我们在地址栏输入一个地址时,如:https://api.douban.com/v2/movie/in_theaters,这是请求豆瓣的一个资源,我们会发现它返回来的是json数据。通过上面的分析,我们知道,script标签是最适合做跨域的,因为在js代码里面会大量的使用到json数据。
所以,接下来说一下如何实现跨域。
一、实现自定义跨域- 方式一
创建script标签,动态添加到页面中。
由于返回的是json数据,但是script标签只能解析js代码,所以这个时候要套一个函数。不然就会报一个错:
原因就是js代码不能直接解析json数据。
(function(){
//定义函数的两种方式
// var test=function(data) {
// console.log(data);
// }
function test(data){
console.log(data);
}
//将test函数挂载到window对象中
window["test"]=test;
var jsonp=function (url) {
var script=document.createElement("script");
script.src=url+"?callback=test";
// 追加到body里面
document.body.appendChild(script);
}
jsonp("https://api.douban.com/v2/movie/in_theaters");
})();
但是这种方式会有一个问题,就是当全局产生了相同的test函数时,就会将其覆盖掉;而且规定了调用的函数,不灵活。
2、 方式二
为了解决上述问题,我们采用回调函数的方法,但是src中又一定要写一个callback函数名,于是我们就用生成随机数,然后用拼接的方式来实现。
(function(){
var jsonp=function (url,callback) {
var funName="fun_"+Math.random().toString().replace(".","");
url=url+"?callback="+funName;
window[funName]=callback;
var script=document.createElement("script");
script.src=url;
// 追加到body里面
document.body.appendChild(script);
}
jsonp("https://api.douban.com/v2/movie/in_theaters",function(data){
console.log(data);
});
注意:url=url+"?callback="+funName;
一定要写?
二、jQuery的ajax跨域
<script>
$(function(){
var success_callback="fun_"+Math.random().toString().replace(".","");
$.ajax({
url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+"阿里",
async:true,
dataType:"jsonp",
type:"get",
//传递给请求处理程序,用以获得jsonp回调函数名的参数名(默认为:callback)
jsonp: "cb",
//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名
cb:"success_callback",
success:function(data){
console.log(data);
},
error:function(err){
}
});
});
</script>
当我把url写成https://api.douban.com/v2/movie/in_theaters地址时,它会报一个错,
这说明豆瓣可能不支持函数名太长或者其他。
所以我把url地址换成了百度搜索的地址。
三、angular实现跨域
(function(angular){
var app=angular.module("myApp",[]);
app.controller("myCtrl",["$scope","$http",function($scope,$http){
var url="https://api.github.com?callback=JSON_CALLBACK";
$http.jsonp(url).success(function(data){
console.log(data);
}).error(function(data){
console.log("111");
});
}]);
})(angular);
将代码放在了自执行函数里面。