本教程里的资料来源于网友的资料,自己整理以供学习。

AJAX学习

Ajax(asynchronous javascript and xml)

Ajax描述了一种主要使用脚本操纵HTTP的Web应用架构,主要特点是使用脚本操纵HTTP和Web服务器进行数据交换,不会导致页面重载

HTTP协议

HTTP协议(HyperText Transfer Protocal): 规定Web浏览器如何从Web服务器获取文档和向Web服务器提交表单内容,以及Web服务器如何响应这些请求和提交

分为请求报文响应报文

请求报文包括:

  1. 请求行

    • HTTP请求的方法(GET或POST)
    • 正在请求的URL
  2. 请求头(可选,包含身份验证信息等)

  3. 请求主体(可选,GET方式没有请求主体)

响应报文包括:

  1. 状态行(由文字和数字组成的状态码,用来显示请求的成功和失败。常见的有200 OK、404 NOT FOUND、304 MODIFIED)

  2. 响应头集合

  3. 响应主体

XMLHttpRequest的使用

浏览器在XMLHttpRequest类上定义了他们的HTTP API。这个类的每个实例都表示一个独立的请求/响应对,并且这个对象的属性和方法允许指定请求细节和提取响应数据

使用基本步骤

GET方式(适用于URL完全指定请求资源且请求对服务器没有任何服务器作用以及服务器的响应是可缓存时):

  1. 实例化XMLHttpRequest对象

    var 变量名 = new XMLHttpRequest()

    1
    var xhr = new XMLHttpRequest();
  2. 设置请求行(设置请求方式和请求url,如果有数据则以 ?key=value 形式添加在URL后面)

    XHR对象.open('GET',请求URL)

    1
    xhr.open('GET','xxx.html?name=bruce');
  3. 设置请求头(GET方式一般不用写)

    XHR对象.setRequestHeader(键名,键值)

    1
    xhr.setRequestHeader('heima','hehe');
  4. 向服务器发送(GET方式没有请求主题)

    XHR对象.send(null或者省略)

    1
    xhr.send(null);

    POST方式(在请求主体中常包含额外数据且这些数据常存储到服务器上的数据库中):

  5. 实例化XMLHttpRequest对象

    var 变量名 = new XMLHttpRequest()

    1
    var xhr = new XMLHttpRequest();
  6. 设置请求行(设置请求方式和请求url)

    XHR对象.open(提交方式,请求URL)

    1
    xhr.open('GET','xxx.html');
  7. 设置请求头(POST一定要写下面的请求头)

    XHR对象.setRequestHeader(键名,键值)

    1
    xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');

    该请求头的作用是让数据仿效表单提交

  8. 向服务器发送(post一般有发送主体,数据作为send函数参数发送)

    XHR对象.send('key1=value&key2=value')

    1
    xhr.send('name=jl&friend=avgs');

    注意:

  9. open中的url参数必须是相对于当前文档的url,否则跨域会报错,除非服务器明确允许跨域请求

  10. HTTP请求各部分有指定顺序: 请求方法和url首先到达,然后是请求头,然后是请求主体,调用XMLHttpRequest的方法必须匹配HTTP请求的架构,比如setRequestHeader必须在open后send前

  11. open可以设置第三个参数为false(默认为true)实现同步处理HTTP响应

服务器接收响应

不同服务器的代码不同、自行百度

注意:

  1. 使用该对象必须在服务器中测试,即对url的访问必须经过服务器。XMLHttpRequest用于同http和https协议一起工作,

  2. 发送请求等待服务器响应时是不阻塞的

  3. 服务器的正确解码是假设服务器为这个响应发送了”Content-Type”头和正确的MIME类型用以告诉浏览器数据应解析为的类型。如下表

响应数据格式应声明的头部
textheader(Content-type: text/plain;charset=utf-8)可不写
XMLheader(Content-type: text/xml;charset=utf-8)必写
jsonheader(Content-type: appliation/json;charset=utf-8)可不写
htmlheader(Content-type:text/html;charset=utf-8)
客户端获取响应数据(一般用在XHR对象异步处理程序内)
  • 字符串形式数据

    responseText可以得到响应主体的文本形式

  • XML形式数据(少用,了解即可)

    responseXML获得Document形式,可以利用选择器获取其中元素的内容

    1
    var name = xhr.responseXML.querySelector("name").innerHTML;
  • JSON形式数据(就是将对象等复杂数组用字符串作为载体传递 其中的所有要解析的键名键值都要用引号包裹**,除非键值是数字,最常用的数据格式)

JSON的特点:

  1. JSON是一种数据的格式

  2. JSON和编程语言没有关系,其载体是字符串,基本上所有的语言都支持字符串

  3. 语法简洁 所有的编程语言都提供了对应的方法解析JSON

JSON语法

  • JSON数据格式

    1
    2
    3
    4
    5
    {
    "name":"bruce",
    "age":"28",
    "skill":"detective"
    }

    注意: 键名键值都要用双引号包裹,整个值用单引号包裹

  • JSON的转换

    JSON.parse(字符串): 将json数据转为对应对象或数组形式

    JSON.stringify(数组或对象): 将对象或数组数据转为json格式

    1
    2
    3
    4
    5
    var JSONArr = '["绿菜花","圣女果","大葱","番茄"]'; 
    console.log(JSON.parse(JSONArr)[1]);//圣女果
    var JSONArr = '{"name":"bruce","skill":"kill","friend":["alfred","clark","diana"]}'; console.log(JSONArr);//输出字符串
    var result = JSON.parse(JSONArr);
    console.log(result.friend[1]);//clark
  • JSON用法

    1. 浏览器发出ajax请求

    2. 服务器端获取ajax数据(可以读取json文件也可以直接写)

      不同服务器的代码不同、自行百度

      注意: 发送json数据的header可写可不写,一般还是写

    3. 浏览器接收数据,转化,渲染

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      xhr.onreadystatechange = function(){ 
      if(this.readyState == 4&&this.status == 200) {
      console.log(this.responseText); // 转化为对应的数据格式
      var arr = JSON.parse(this.responseText);
      console.log(arr);
      for(var i = 0;i < arr.length;i++){
      console.log('姓名:'+ arr[i]["name"] + '技能:' + arr[i]["skill"]);
      }
      }
      }
客户端异步处理HTTP响应
  1. 用onload函数,当服务器成功接收到文件时,触发load事件,调用其中回调函数

    1
    2
    3
    4
    xhr.onload = function(){ 			
    console.log('hi!'); // responseText 获取响应报文
    console.log(xhr.responseText);
    }
  2. 使用onreadystatechange函数,当XHR对象的readyState属性发生变化时就会触发并调用其中回调函数

    readyState属性返回一个XHR对象当前所处的状态,其值主要有:

    状态描述
    0UNSENT代理被创建,但尚未调用 open() 方法
    1OPENEDopen()方法已经被调用
    2HEADER_RECEIVEDsend()方法已经被调用,并且头部和状态已经可获得
    3LOADING下载中;responseText属性已经包含部分数据
    4DONE下载操作已完成

    一般可以和status属性配合使用检测XHR对象是否接受到数据。

    statue属性返回XHR对象的响应状态吗。成功一般为200,找不到上传url会返回404

    可以利用以下代码完成更健壮的响应检测

    1
    2
    3
    4
    5
    xhr.onreadystatechange = function(){ 
    if(this.readyState == 4 && this.status == 200) {
    console.log('我触发一次');
    }
    }
判断响应数据类型

可以利用xhr对象的getResponseHeader(获取内容)方法来获取响应头的内容

检验是否是json

1
/json/.test(xhr.getResponseHeader("Content-type"))

检验是否是xml

1
/xml/.test(xhr.getResponseHeader("Content-type"))

jQuery中的Ajax

jquery的get快捷函数

jQuery.get( url [, data ] [, success ] [, dataType ] )

参数亦可以写成对象形式jQuery.get({url:"xxx.html",data:"key=value",success:function(x){alert(x)}})

参数信息:

  • url:提交地址

  • data: 提交数据,格式可以为键值对字符串也可以是对象形式

  • success: 接收到数据后的回调函数,其中的第一个参数就是接收到的数据

  • dataType: 从服务器返回的预期的数据类型

    1
    2
    3
    $.get("data.html",{name:"bruce",husband:"diana"},function(x){alert(x)}); 

    $.get("data.html","name=rose&husband=jack",function(x){alert(x)});

    jquery的post快捷函数

jQuery.post( url [, data ] [, success ] [, dataType ] ) 同样的,参数也可以写成对象形式

参数信息:

  • url:提交地址

  • data: 提交数据,格式可以为键值对字符串也可以是对象形式

  • success: 接收到数据后的回调函数,其中的第一个参数就是接收到的数据

  • dataType: 从服务器返回的预期的数据类型

    1
    $.post("data.html","name=bruce",function(x){alert(x)});

jQuery的ajax函数(可以自己选择post还是get)

参数必须以对象形式写

jQuery.ajax({url:"xxx.html",type:"get",data:"name=bruce",success:function(x){console.log(x)}})

参数信息:

  • url:提交地址

  • type: 提交方式

  • data: 提交数据,格式可以为键值对字符串也可以是对象形式

  • beforesend:ajax请求发出前执行的函数

  • success: 接收到数据后的回调函数,其中的第一个参数就是接收到的数据,,第二个参数是jQuery状态码,第三个是XHR对象

  • error:当响应发生错误时触发,可以接受三个参数,依次代表发起请求的xhr对象,jQuery状态码,发生错误的位置

  • complete: 请求完全完成时触发

  • dataType: 可以自己声明接收的数据类型而不需要后台声明,包括json、xml等

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    $.ajax({ 		
    url:'json.php',
    data:{
    name:"bruce",
    skill:"kill"
    },
    success:function(data){
    console.log(data);
    },
    // error属性在请求失败时会触发
    error:function(XMLHttpRequest,textStatus,errorThrown){
    console.log('error');
    // xhr对象信息
    console.log(XMLHttpRequest);
    // 错误类型
    console.log(textStatus);
    // 错误位置
    console.log(errorThrown);
    },
    // 请求完成时触发(readyStatus == 4时触发)
    complete:function(){
    console.log('done');
    }
    })

jQuery的其他ajax相关函数

$(document).ajaxStart(function(){})

document中的任意ajax事件触发时便会触发这个事件中,调用其中回调函数,必须绑定在document上

1
2
3
$(document).ajaxStart(function() { 		
$(".cover").show();
});

$(document).ajaxComplete(function(){})

document中的任意ajax事件刚完成时便会触发这个事件,调用其中回调函数,必须绑定在document上

1
2
3
$(document).ajaxComplete(function() { 		
$(".cover").hide();
});

附: jQuery的Ajax状态码

success请求成功完成
notmodified请求以正常完成,但是url内容与上次相同
error请求没有完成,发生某些http错误
timeout没有在规定时间内完成
parsererror请求完成,但无法正常解析数据,比如服务器中的数据格式错误

模板和模板引擎的使用

以template-web引擎为例

模板

即写好的等待被模板引擎渲染数据的html脚本

模板引擎

渲染模板的脚本

模板的创建

用一个script标签,声明其类型为html,然后写入html脚本

1
2
3
4
5
6
7
8
<script type="text/html" id="template"> 		
<ul>
<!-- 用{{}}代表数据填充位置 -->
<li>名字{{name}}</li>
<li>技能{{skill}}</li>
<li>爱好{{hobby}}</li>
</ul>
</script>

注意要写ID,才能被模板引擎找到渲染。其中以 {{键名}} 指定待填充数据的位置

模板的渲染

利用模板引擎的template函数

  1. template(渲染的脚本id,保存渲染数据的对象) 返回填充好的字符串,而不是返回节点

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var data = { name:'bruce', skill:'kill', hobby:'coding' }
    var result = template('template',data);
    console.log(result);

    //结果为
    /*
    <ul>
    <!-- 用代表数据填充位置 -->
    <li>名字bruce</li>
    <li>技能kill</li>
    <li>爱好coding</li>
    </ul>
    */

    注意: 对象中的键名必须和模板中填充位置的名字一样

  2. 然后就可以将模板渲染到页面中

    1
    document.body.innerHTML = result;

模板引擎的原理(自己封装)

1
2
3
4
5
6
7
8
function template(id,obj){ 		
var script = document.querySelector("#"+id);
script = JSON.stringify(script.innerHTML);
for(var k in obj) {
script = script.replace("{{"+ k +"}}",obj[k]);
}
return JSON.parse(script);
}

模板引擎其他语句

判断语句

{{if}} {{else}} {{else if}} 用于判断 以{{/if}}结束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{{if male=='girl'}} 
<li>welcome,mr.{{name}}
<ol>
<li>bag</li>
<li>kouhong</li>
<li>wow you are{{skill}}</li>
</ol>
</li>
{{else if male =='man'}}
<li>welcome,mr.{{name}}
<ol>
<li>drag</li>
<li>come on</li>
<li>wow you are{{skill}}</li>
</ol>
</li>
{{/if}}

输出原文(加@符号即可)

{{@xxx}} 可以按照其格式解析内容

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul> 		
<li>{{name}}</li>
<li>{{skill}}</li>
<li>{{@info}}</li>//显示为a标签而不是字符串
</ul>
<script type="text/javascript">
var person = {
name:'monkey king',
skill:'fly',
info:'<a href="http://www.baidu.com" title="">monkeyking</a>'
}
document.body.innerHTML = template('norTemplate',person);
</script>
循环语句

{{each 循环的属性}} $value(其中的数值) {{/each}} 结束循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<ol>家人们 
{{each family}}
<li>{{$value['name']}},he can {{$value['skill']}}</li>
{{/each}}
</ol>
<script type="text/javascript">
var person = {
name:'big',
brother:[
'two',
'three',
'four',
'five',
'six', 'seven'
],
family:[
{name:'yeye',skill:'captured'},
{name:'chuanshanjia',skill:'what say'},
{name:'butterfly',skill:'fish'}
]
}
console.log(template('brothers',person));
</script>

跨域解决方案

  • 同源:协议、主机、端口都一样就是同源

  • 不同源: 协议主机端口有一个不一样就是不同源

  • 跨域: 不同源的网站之间发送请求就是跨域

两种跨域解决方案

  1. 利用CORS(Cross-Origin Resource Share):

    在后台数据文件中添加头header("Acess-Control-Allow-origin:\*");

    实现条件:

    • 浏览器支持CORS

    • 请求的网站开启CROS

      缺点: HTML5才支持

  2. 利用JSONP(JSON with Padding)

    只需设置script标签的src属性

    原理: 利用标签src属性可以获取跨域资源的原理,在src中将函数方法等数据传给服务器,服务器中再采用JSON的格式输出,浏览器获得该数据后会自动按照JS语法解析,实现对数据的处理

    优点:

    • 不受同源策略限制

    • 会自动解码执行包含JSON编码数据的响应体

      注意:

    1. src属性充当了Ajax,JSONP与Ajax无关,JSONP只需要一个src属性指向请求地址的script标签

    2. 回调函数一般统一叫callback

    3. JSONP只能发送get请求,不能发送post请求

    4. jQuery中的JSONP的原理是动态创建了script标签,其中src等于请求地址+”?”+success方法

    5. img不用于JSONP的原因是img的src属性能发送数据,但是服务器的响应一直是一张图片导致客户端无法轻易从中提取信息

    6. iframe不用于JSONP的原因是其受限于同源策略

    7. 对于不可信任的服务器,不该使用这项技术

    8. 响应内容必须用JS函数名和圆括号包裹起来

  3. 利用跨域消息传递(window对象的postMessage方法,HTML5新增)

    window对象的postMessage方法允许来自非同源的脚本调用,允许有限的通信,通过异步传递的方法。这项技术称为”跨文档消息传递”

    步骤(以open打开新窗口为例):

    1. 弹出一个用于发送信息的窗口

      1
      var w = window.open('http://192.168.43.112/anotherWayCrossOrigin/receiver.html');
    2. 在弹出的窗口中,打开这个页面的页面向自己传递数据,达到跨域的效果

      Window.postMessage(data,url)

      data:任意基本类型或者可以复制的对象,如果想要传递数组或对象可以用JSON数据

      url:指定目标窗口的源(注意是源而不是某个文件,包括协议主机名和端口,除了这些以外的其他参数会被忽略),会传给指定url下的任何页

      如果设置为*,则可以传递给任何窗口。如果设定为/,则只能传给与当前页面同源的文件

      1
      var arr = ['ha','hey','he']; window.opener.postMessage(JSON.stringify(arr),"http://127.0.0.1//anotherWayCrossOrigin/index.html");
    3. 在最初页面中,Window对象调用message事件异步处理接收到的信息

      可以利用该事件的事件对象的属性获取数据,其中包括:

      • e.data 接收到的数据

      • e.source 数据源自的Window对象

      • e.origin一个字符串,指定消息来源(URL格式)

        1
        2
        3
        4
        5
        window.onmessage = function(e){ 
        console.log(JSON.parse(e.data));// ["ha", "hey", "he"]
        console.log(e.source);//Window对象
        console.log(e.origin);//http://192.168.43.112
        }

原理总结: 让接收信息的页面跑到发送信息的页面向自己发送信息 发送信息的页面必须是接收信息的页面打开的

跨域消息传递可用于解决以下方面的问题:

  • iframe嵌套页面跨域通信
  • 页面和其打开的新窗口的通信
  • 多窗口之间消息传递

XMLHttpRequest2.0

1.快速格式化表单数据

利用FormData对象快速格式化form表单元素,然后作为发送主体传送

1
var sendData = new FormData(document.querySelector("form")); xhr.send(sendData);

2.ajax上传文件

在上面方法基础上在form中添加file表单即可

3.上传进度监控(兼容性一般)

利用xhr对象upload属性的progress事件的事件对象监听上传进度

upload:代表上传过程

e.loaded:已经上传的数据大小

e.total:传输完成的数据大小

1
2
3
4
5
xhr.upload.onprogress = function(e){ 	
// console.log(e);
console.log(e.loaded / e.total);
document.querySelector(".step").style.width = ((e.loaded / e.total) * 200) + 'px';
}