Ajax(asynchronous javascript and xml)
Ajax描述了一种主要使用脚本操纵HTTP的Web应用架构,主要特点是使用脚本操纵HTTP和Web服务器进行数据交换,不会导致页面重载
 
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()
var xhr = new XMLHttpRequest();
2.设置请求行(设置请求方式和请求url,如果有数据则以?key=value形式添加在URL后面)
XHR对象.open(提交方式,请求URL)
xhr.open('GET','xxx.php?name=bruce');
3.设置请求头(GET方式一般不用写)
XHR对象.setRequestHeader(键名,键值)
xhr.setRequestHeader('heima','hehe');
4.向服务器发送(GET方式没有请求主题)
XHR对象.send(null或者省略)
xhr.send(null);

 

POST方式(该方式运用在请求主体中常包含额外数据且这些数据常存储到服务器上的数据库中的情况):
1.实例化XMLHttpRequest对象
var 变量名 = new XMLHttpRequest()
var xhr = new XMLHttpRequest();
2.设置请求行(设置请求方式和请求url)
XHR对象.open(提交方式,请求URL)
xhr.open('GET','xxx.php');
3.设置请求头(POST如果有发送数据一定要写下面的请求头)
XHR对象.setRequestHeader(键名,键值)
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
该请求头的作用是让数据仿效表单提交
4.向服务器发送(post一般有发送主体,数据作为send函数参数发送)
XHR对象.send(‘key1=value&key2=value’)
xhr.send('name=jl&friend=avgs');
 
注意:
1.open中的url参数必须是相对于当前文档的url,否则跨域会报错,除非服务器明确允许跨域请求
2.HTTP请求各部分有指定顺序:请求方法和url首先到达,然后是请求头,然后是请求主体,调用XMLHttpRequest的方法必须匹配HTTP请求的架构,比如setRequestHeader必须在open后send前
3.open可以设置第三个参数为false(默认为true)实现同步处理HTTP响应
 
服务器接收响应
同样用超全局变量$_GET/$_POST接收
<?php sleep(3); echo 'hi'; // 使用get提交过来的数据 使用$_GET获取 print_r($_GET);//Array([name] => jack[skill] => painting) print_r($_GET['name']); ?>
注意:
1.使用该对象必须在服务器中测试,即对url的访问必须经过服务器。XMLHttpRequest用于同http和https协议一起工作,
2.发送请求等待服务器响应时是不阻塞的
3.服务器的正确解码是假设服务器为这个响应发送了“Content-Type”头和正确的MIME类型用以告诉浏览器数据应解析为的类型。如下表
 
响应数据格式
应声明的头部
text
header(Content-type:text/plain;charset=utf-8)可不写
XML
header(Content-type:text/xml;charset=utf-8)必写
json
header(Content-type:appliation/json;charset=utf-8)可不写
HTML
header(Content-type:text/html;charset=utf-8)必写
 
客户端获取响应数据(一般用在XHR对象异步处理程序内)
字符串形式数据
responseText可以得到响应主体的文本形式
 
XML形式数据(少用,了解即可)
responseXML获得Document形式,可以利用选择器获取其中元素的内容
var name = xhr.responseXML.querySelector("name").innerHTML;
 
JSON形式数据(就是将对象等复杂数组用字符串作为载体传递 其中的所有要解析的键名键值都要用引号包裹,除非键值是数字,最常用的数据格式)
JSON的特点:
1.JSON是一种数据的格式
2.JSON和编程语言没有关系,其载体是字符串,基本上所有的语言都支持字符串
3.语法简洁 所有的编程语言都提供了对应的方法解析JSON
 
JSON语法
JSON数据格式
 '{"name":"bruce","age":"28","skill":"detective"}'; echo '["name","age"]';
注意:键名键值都要用双引号包裹,整个值用单引号包裹
 
JSON的转换
JSON.parse(字符串) 将json数据转为对应对象或数组形式
JSON.stringify(数组或对象) 将对象或数组数据转为json格式
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文件也可以直接写)
header("content-type:appliaction/json;charset=utf-8"); echo '{name:bruce,age:28,skill:detective}'; echo file_get_contents('data.json');
注意:发送json数据的header可写可不写,一般还是写
3.浏览器接收数据,转化,渲染
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事件,调用其中回调函数
xhr.onload = function(){ console.log('hi!'); // responseText 获取响应报文 console.log(xhr.responseText); }

 

2.使用onreadystatechange函数,当XHR对象的readyState属性发生变化时就会触发并调用其中回调函数
readyState属性返回一个XHR对象当前所处的状态,其值主要有:
一般可以和status属性配合使用检测XHR对象是否接受到数据。
statue属性返回XHR对象的响应状态吗。成功一般为200,找不到上传url会返回404
可以利用以下代码完成更健壮的响应检测
xhr.onreadystatechange = function(){ if(this.readyState == 4 && this.status == 200) { console.log('我触发一次'); } }
 
注意:对于php语言,如果接受输出多个数据,那么客户端会受到一串很多数据连起来的数据,如果数据不多,可以再php中输出特定符号,然后在客户端根据该符号将信息分开。如果数据太多,则一般以JSON格式传送数据
 
判断响应数据类型
可以利用xhr对象的getResponseHeader(获取内容)方法来获取响应头的内容
检验是否是json
/json/.test(xhr.getResponseHeader("Content-type"))
检验是否是xml
/xml/.test(xhr.getResponseHeader("Content-type"))

 

jQuery中的Ajax
jquery的get快捷函数
jQuery.get( url [, data ] [, success ] [, dataType ] )
参数亦可以写成对象形式
jQuery.get({url:"xxx.php",data:"key=value",success:function(x){alert(x)}})
参数信息:
url:提交地址
data:提交数据,格式可以为键值对字符串也可以是对象形式
success:接收到数据后的回调函数,其中的第一个参数就是接收到的数据
dataType:发送数据类型
$.get("data.php",{name:"bruce",husband:"diana"},function(x){alert(x)}); $.get("data.php","name=rose&husband=jack",function(x){alert(x)});
 
jquery的post快捷函数
jQuery.post( url [, data ] [, success ] [, dataType ] ) 同样的,参数也可以写成对象形式
参数信息:
url:提交地址
data:提交数据,格式可以为键值对字符串也可以是对象形式
success:接收到数据后的回调函数,其中的第一个参数就是接收到的数据
dataType:发送数据类型
$.post("data.php","name=bruce",function(x){alert(x)});
 
jQuery的ajax函数(可以自己选择post还是get)
参数必须以对象形式写
jQuery.ajax({url:"xxx.php",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等
$.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上
$(document).ajaxStart(function() { $(".cover").show(); });
 
$(document).ajaxComplete(function(){})
document中的任意ajax事件刚完成时便会触发这个事件,调用其中回调函数,必须绑定在document上
$(document).ajaxComplete(function() { $(".cover").hide(); });
 
附:jQuery的Ajax状态码
 
success
请求成功完成
notmodified
请求以正常完成,但是url内容与上次相同
error
请求没有完成,发生某些http错误
timeout
没有在规定时间内完成
parsererror
请求完成,但无法正常解析数据,比如服务器中的数据格式错误
模板和模板引擎的使用(以template-web引擎为例)
模板:即写好的等待被模板引擎渲染数据的html脚本
模板引擎:渲染模板的脚本
 
模板的创建(用一个script标签,声明其类型为html,然后写入html脚本)
<script type="text/html" id="template">
 <ul> <!-- 用{{}}代表数据填充位置 --> 
<li>名字{{name}}</li> 
<li>技能{{skill}}</li> 
<li>爱好{{hobby}}</li>
 </ul>
 </script>
注意要写ID,才能被模板引擎找到渲染。其中以{{键名}}指定待填充数据的位置
 
模板的渲染
利用模板引擎的template函数
1.template(渲染的脚本id,保存渲染数据的对象) 返回填充好的字符串,而不是返回节点
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.然后就可以将模板渲染到页面中
document.body.innerHTML = result;

 

模板引擎的原理(自己封装)
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}}结束
{{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}} 可以按照其格式解析内容
<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 <ol>家人们
 2  {{each family}} 
 3 <li>{{$value['name']}},he can {{$value['skill']}}</li>
 4  {{/each}}
 5  </ol>
 6  <script type="text/javascript">
 7  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'} ]
 8  } 
 9 console.log(template('brothers',person));
10  </script>

 

 
跨域解决方案
同源:协议、主机、端口都一样就是同源
不同源:协议主机端口有一个不一样就是不同源
跨域:不同源的网站之间发送请求就是跨域
 
两种跨域解决方案
1.利用CORS(Cross-Origin Resource Share):
在后台数据文件中添加头header("Acess-Control-Allow-origin:*");
实现条件:1.浏览器支持CORS 2.请求的网站开启CROS
缺点:HTML5才支持
<?php header('Access-Control-Allow-Origin:*'); echo '你来了呀'; ?>
 
2.利用JSONP(JSON with Padding)
只需设置script标签的src属性
原理:利用标签src属性可以获取跨域资源的原理,在src中将函数方法等数据传给服务器,服务器中再采用JSON的格式输出,浏览器获得该数据后会自动按照JS语法解析,实现对数据的处理
优点:1.不受同源策略限制 2.会自动解码执行包含JSON编码数据的响应体
客户端 
<script>
 function dosomething(data) { for(var k in data) 
{ console.log(k); console.log(data[k]); } }
 </script> 
<script src="http://192.168.43.112/data.php?callback=dosomething"></script>
 服务器端 
<?php $something = $_GET['callback']; echo $something.'({"name":"jack","age":29})'; ?>
注意:
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函数名和圆括号包裹起来