First, the concept of Ajax
- Ajax is a technical solution , but not a new technology. It relies on the existing CSS/HTML/Javascript, and the core dependency is the XMLHttpRequest object provided by the browser, which enables the browser to issue HTTP requests and receive HTTP responses.
- Ajax: Asynchronous JavaScript and XML
- Asynchronous js: The code of js is executed from the beginning to the end. If a piece of code is not executed, the following code will not be executed. Asynchronous means that ajax can be executed out of order;
- Ajax can not only process data in XML format, but also process data of json, array, and string type;
XML: A format for storing data:
//XML的格式类型; <name>陈学辉</name> <age>18</age> <qq>356985332</qq> <email>[email protected]</email>
What can ajax do:
A technology for data interaction between js and the backend, by requesting the negotiated interface to obtain the desired data
advantage
When transmitting data, the server will be requested on this page without jumping the page, thereby reducing the pressure on the server. Real-time verification, reducing user rework and optimizing user experience
2. Ajax data interaction process
Create an ajax object;
var val=inputs[0].value; //下面这个是ajax对象; var ajax=new XMLHttpRequest;
Fill in the request address;
```
//open is a method on the ajax object;
ajax.open("get","php/get.php?user="+val,true);
//The first parameter determines whether it is get or post;
//The second parameter is the request address, and the one to be submitted is added;
//The third parameter true means asynchronous, false means synchronous;
- 发送请求;
ajax.send();
- 等待服务器响应;
ajax.onload=function(){
//Accept the data after the response is completed;
span.innerHTML=ajax.responseText;
}
- 接收数据;
##三、返回的数据类型
> **ajax.responseText**这是服务器返回的值:
1.肯定是字符串,有的看起来是对象,其实是json的形式;
2.用JSON的方法:`JSON.parse(aja.responseText)`转成真正的对象就可以用对象操作的方法去操作了;
##四、XHR的兼容问题
- **XMLHttpRequest**是标准浏览器下的升级版本,IE6这些浏览器不支持;
- IE6下用**ActiveXObject(Microsoft.XMLHTTP)**
//Write a compatibility function to achieve cross-browser;
var ajax=null;
if(window.XMLHttpRequest){
ajax=new XMLHttpRequest;
}else{
ajax=new ActiveXObject(Microsoft.XMLHTTP)
};
##五、get和post的区别
- get方式
- 通过地址栏信息进行数据传输,传输的大小有限制;
- 不安全,用户的所有信息都会暴露出来;
- 拼接数据的时候要用`encodeURI`转一下码,不然有中文就会乱码;
> `encodeURI`把文字转成符号;
`decodeURI`把符号转成文字;
- 不用设置请求头;
- 数据拼接在open方法里;
- 会有缓存问题;
- post方式
- 通过send向服务器传输数据,理论上来说是没有长度或体积限制;
- 相对来说安全,因为不直接暴露用户信息;
- 不用转码,已经通过请求头设置了数据格式,不会有乱码;
- 数据要拼接在send方法里;
- 没有缓存问题
- 在send()的前面需要设置一个请求头(不设置要出错);
ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
//Create an object;
var ajax=null;
if(window.XMLHttpRequest){
ajax=new XMLHttpRequest;
}else{
ajax=new ActiveXObject(Microsoft.XMLHTTP)
};
//Fill in the request address;
ajax.open("post", "php/post.php",true);
//To send a request, set the request header before send;
ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
ajax. send("user="+val)
//The following steps are the same as the get method;
##六、同步与异步
- 同步
> 1、当`send()`方法调用后会等待服务器返回信息,如果服务器一直没有响应,就会阻塞后面的代码,后面的代码就不会执行
2、后面的代码执行受前面代码的影响,前面的代码没跑通,后面的代码就不会执行
- 异步
>> 1、当`send()`方法调用后,就会执行后面的代码,不用等待服务器的响应
2、后面的代码执行不受前面代码的影响
##七、onreadystatechange与onload
- `ajax.readState`ajax的运行步骤(第一步捕捉不到)
- 它的值为4的话说明AJAX已经运行完毕;
- *0* 代表初始化,还没调用**open**方法;
- *1* 代表载入,已经调用**send**方法,正在发送请求;
- *2* 代表载入完成,send方法已完成,已收到全部响应内容;
- *3* 代表正在解析响应内容;
- *4* 代表响应完成,可以在客户端调用了;
- `ajax.status`(状态码)
- 200是成功的;
- 404是错误的;
- `onreadStateChange`
> `readstate`的值发生变化就会触发这个事件;
- `onload`
> >所有请求成功完成后触发,此时的`readstata`的值为**4**
**IE(6,7,8)不支持**
**现在这个方法逐渐取代`onreadstatechange`这个方法了**
ajax.onreadstatechange=function(){
if(ajax.readstate==4){ //The response of the service area is completed;
if(ajax.status==200){ //The server is normal;
//The code to be executed is placed here;
}
}
}
##八、封装ajax函数
> 封装ajax函数,传进函数里面的参数其实是一个**对象**;
- 对象中包包含以下几种数据,包含在一个对象里面:
- URL:发送请求的地址,需要把请求发给谁;
- method:发送请求的方法:get或者post;
- dataType:响应之后返回的数据类型:JSON,XML,STRING;
- data:请求的时候传的数据(它是一个对象需要处理格式);
- succ:成功之后的callback;
- fail:失败后的callback;
function ajax(json){
//默认参数;
var settings={
url:"",
method:"get",
data:{},
dataType:"json",
succ:null,
fail:null
}
//用户传的参数覆盖默认参数;
for (var attr in json){
settings[attr]=json[attr];
}
//把data拼成正确的格式;
var arr=[];
for (var attr in settings.data){
arr.push(attr+"="+settings.data[attr]);
}
settings.data=arr.join("&");
//声明变量;
var ajax=window.XMLHttpRequest?new XMLHttpRequest():ActiveXObject("Microsoft.XMLHTTP");
//设置请求方式;
//请求地址里面的new Date()方法,是为了设置不同的时间戳去解决缓存的问题;
if(settings.method.toLocalLowCase==="get"){
ajax.open("get",settings.url+"?"+settings.data+"&"+new Date().getTime(),true);
ajax.send();
}else{
ajax.open("post",settings.url,true);
//注意要设置一个请求头;
ajax.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
ajax.send(settings.data);
}
//设置完成时间的兼容性;IE6下是没有ajax.onload方法的;
if(typeof ajax.onload==="undefined"){
ajax.onreadystatechange=ready;
}else{
ajax.onload=ready;
}
//封装一个ready()函数;
function ready(){
if(ajax.readystate==4){
if(ajax.status==200){
//用一个switch判断返回值得类型;
switch(settings.dataType.toLocalLowCase()){
case "string" :
settings.succ(ajax.responseText);
break;
case "json" :
//把responsetext转成json格式;
setting.succ(JSON.parse(ajax.responseText));
break;
case "xml" :
settings.succ(ajax.responseXml);
break;
}
}else{
settings.fail(ajax.status);
}
}
}
}
> 要注意第**57**行的**JSON.parse**在低版本的浏览器中是不兼容的,需要下载一个**json2.js**的文件解决这个问题;
##九、ajax上传
- 上传只能用 **post** 的方法,后台要处理中文相关的问题;
- ajax.upload.onprogress 上传的进度事件;就是上传的时候要做的事情;
- `ev.loaded` 已经上传的文件大小;
- `ev.total` 总的文件大小;
> 通过这个可以做出来一个上传的进度条;
用H5中的`<progress></progress>`这个API;
- **files** 上传的选中的文件列表;
>>1.包括文件大小、类型、最后修改的时间等等;
2.放在`type="file"`的表单空间中;
- FormData 用来创建与表单格式相同的数据,它是XHR的二级定义,是一个**二进制**的数据;**低版本的浏览器不支持**;
>>> **我自己对于FormData的理解:
FormDate可以new出来一个实例,这个实例可以继承它身上的append方法;这个操作放在`ajax.open`和`ajax.send`之间**
var formdata=new FormData();
//下面通过循环把选中的文件里面的额东西添加到这个对象身上;
for(var i=0;i<inputs[0].files.length;i++){
//inputs[0]指的是一个type="file"的表单控件;
formdata.append("file",inputs[0].files[i]);
}
//这时候formdata就可以被发送给服务器了,前面加上一个请求头;
##十、跨域的问题
- 概念:
> 两个不同域名下的数据进行交互。Ajax之所以不能跨域其实是因为XMLHttpRequest受到**同源策略**的限制,只能让它访问同源下的数据,不能访问不同源下的数据;
- 同源策略:
>> 每个网站只能读取同一来源的数据,这里的同一来源指的是主机名(**域名**)、**协议**(http/https)和**端口号**的组合。在没明确授权的情况下,不能读写对方的资源,它是浏览器最核心也最基本的安全功能;
**只要有一个不一样就跨域;**
- 解决跨域的方法:
- 在标准浏览器下XMLHttpRequest配合后端设置一个请求权限,在php里写上 header('Access-Control-Allow-Origin:*');
- 服务器代理,缺点是后端开发的成本大;
- iframe、flash、postMessage、WebSocket;
>>> 这些方法都不是最优的,下面提供一种方法叫做 **jsonp**
##十一、jsonp
- jsonp的概念(json+padding)
- 通过script标签引入某些数据,是同步模式的,用script标签做跨域的时候,不建议将数据提前加载,需要**按需加载**;
- 当需要数据的时候创建一个script标签,将需要的数据放在src中,通过onload去监听是否请求过来,请求完毕就调用传回来的数据(异步加载);
- jsonp不能用post请求,只能是get请求;
> 带src属性的<script><img><iframe><link>等标签是不需要遵守同源策略的,但是通过src加载的资源,浏览器限制了javascript的权限,**能读不能写**;这就是jsonp能实现跨域的原因;
- jsonp中的回调函数
- 通过jsonp的方式的数据一般都会放在一个回调函数里;
- 请求到的结果是这样的`getData({"color":["red","green","blue"]})`
- 数据放在函数的参数里,可以是任何数据形式(对象、数组)
- 回调函数的名字要么是后端定死的,要么是我们在请求地址跟动态加上的
>> 注意**callback**是要设置成全局的,要不就放在操作的前面;
- 封装一个jsonp
function jsonp(obj){
var settings={
url:'', //address
data:{}, //data to be sent
callBack:'callback', //the variable
fnName:'jsonp_' that stores the name of the callback function in the url +new Date().getTime(), //name of callback function
succ:function(){} //callback function for successful request
};
for(var attr in obj){
settings[attr]=obj[attr];
}
//创建一个script标签
var script=document.createElement("script");
script.className='sc';
settings.data[settings.callBack]=settings.fnName;
var head=document.getElementsByTagName('head')[0];
//把要传的数据拼起来
var arr=[]; //['wd=sds','cb=jQuery1']
for(var attr in settings.data){
arr.push(attr+'='+settings.data[attr]);
}
settings.data=arr.join('&');
script.src=settings.url+'?'+settings.data;
head.appendChild(script);
//把回调函数挂载到window身上
window[settings.fnName]=function(data){
//当调用这个函数的时候,先把页面中所有的已经请求过的script删掉
var scripts=head.getElementsByTagName('script');
for(var i=0;i<scripts.length;i++){
if(scripts[i].className=='sc'){
head.removeChild(scripts[i]);
}
}
settings.succ(data);
};
}
```