Ajax跨域
-
同源策略
-
同源策略是浏览器的一种安全策略,所谓同源指的是请求URL地址中的协议、域名和端口都相同,只要其中之一不相同就是跨域。
-
同源策略主要为了保证浏览器的安全性。
-
在同源策略下,浏览器不允许Ajax跨域获取服务器数据。
-
http://www.example.com/detail.html
跨域解决方案
-
jsonp (仅仅是get请求方式)
-
document.domain+iframe
-
location.hash + iframe
-
window.name + iframe
-
window.postMessage
-
flash等第三方插件
jsonp 原理
-
静态script标签的src属性进行跨域请求
<script src="http://www.ajaxDemo.cc/check.php"></script> <!-- 同步加载 --> <!--<script src="http://www.ajaxDemo.cc/check.php" async></script>--> <!-- async 异步加载 --> <script > /* 这种方式存在的两个主要的问题: 1、必须保证加载的顺序 2、不方便通过程序传递参数 */ console.log(data) </script>
-
动态创建script标签,通过标签的src属性发送请求(异步请求)
<script> var script = document.createElement('script'); script.src = 'http://www.ajaxDemo.cc/check.php?callback=foo'; var head = document.getElementsByTagName('head')[0]; head.appendChild(script); function foo(data){ console.log(data) } </script>
// check.php $cb = $_GET['callback']; $data = '{"code":"2","msg":"登录失败"}'; echo "$cb($data)";
原理:
动态创建script
标签,然后通过它的src
属性发送跨域请求,然后服务器端响应的数据格式为【函数调用(foo(实参))】,所以在发送请求之前必须先声明一个函数(foo),并且函数的名字与参数中传递的名字要一致。这里声明的函数是由服务器响应的内容(实际就是一段js代码-函数调用)来调用。
- 需要注意的是,callback参数定义是需要前后端定义好的,具体什么名字,商讨好就可以了
jQuery 对 jsonp 的支持
$.ajax({
url: 'http://www.ajaxDemo.cc/check.php',
type:'get',
dataType: 'jsonp', //指定服务器返回的数据类型
jsonp:'cb', //指定参数名称,默认是callback
jsonpCallback:'abc', //指定回调函数名称,默认是 "jQuery" + ( version + Math.random() ).replace( /\D/g, "" )+当前时间毫秒数
data:{},
success: function(res){
console.log(res)
},
error:function(err){
console.log(err)
}
})
jsonp 接口
-
基于jsonp的常见功能
-
搜索智能提示
-
快递查询
-
-
第三方接口介绍(json/jsonp)
模拟 jQuery jsonp封装可跨域请求
function ajax(obj){
var defaults = {
type : 'get',
async : true,
url : '#',
dataType : 'text',
jsonp : 'callback',
data : {},
success:function(data){console.log(data);}
}
for(var key in obj){
defaults[key] = obj[key];
}
if(defaults.dataType == 'jsonp'){
ajax4Jsonp(defaults);
}else{
ajax4Json(defaults);
}
}
function ajax4Json(defaults){
// 1、创建XMLHttpRequest对象
var xhr = null;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
// 把对象形式的参数转化为字符串形式的参数
/*
{username:'zhangsan','password':123}
转换为
username=zhangsan&password=123
*/
var param = '';
for(var attr in defaults.data){
param += attr + '=' + defaults.data[attr] + '&';
}
if(param){
param = param.substring(0,param.length - 1);
}
// 处理get请求参数并且处理中文乱码问题
if(defaults.type == 'get'){
defaults.url += '?' + encodeURI(param);
}
// 2、准备发送(设置发送的参数)
xhr.open(defaults.type,defaults.url,defaults.async);
// 处理post请求参数并且设置请求头信息(必须设置)
var data = null;
if(defaults.type == 'post'){
data = param;
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
// 3、执行发送动作
xhr.send(data);
// 处理同步请求,不会调用回调函数
if(!defaults.async){
if(defaults.dataType == 'json'){
return JSON.parse(xhr.responseText);
}else{
return xhr.responseText;
}
}
// 4、指定回调函数(处理服务器响应数据)
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
var data = xhr.responseText;
if(defaults.dataType == 'json'){
// data = eval("("+ data +")");
data = JSON.parse(data);
}
defaults.success(data);
}
}
}
}
function ajax4Jsonp(defaults){
// 这里是默认的回调函数名称
// expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
var cbName = 'jQuery' + ('1.11.1' + Math.random()).replace(/\D/g,"") + '_' + (new Date().getTime());
if(defaults.jsonpCallback){
cbName = defaults.jsonpCallback;
}
// 这里就是回调函数,调用方式:服务器响应内容来调用
// 向window对象中添加了一个方法,方法名称是变量cbName的值
window[cbName] = function(data){
defaults.success(data);//这里success的data是实参
}
var param = '';
for(var attr in defaults.data){
param += attr + '=' + defaults.data[attr] + '&';
}
if(param){
param = param.substring(0,param.length-1);
param = '&' + param;
}
var script = document.createElement('script');
script.src = defaults.url + '?' + defaults.jsonp + '=' + cbName + param;
var head = document.getElementsByTagName('head')[0];
head.appendChild(script);
}
基本使用:
ajax({
url:'',
type:'get',
data:{},
dataType:'jsonp'
success: function(res){
console.log(res)
}
})