以前项目中一直在使用$.ajax进行异步请求,今天同事问我会不会原生ajax,那还用问嘛,可他说:"不对不对,再深一层"...
然后我就怀着好奇心与惭愧心(因为真的没想到过啊)到网上取经来了...
现在把核心点整理出来,记录在案吧
首先说明ajax不是一门语言,而是用已存在的知识整合而成的一种框架
ajax能够实现与服务器的数据交互,并且对网页进行部分刷新(不必重新加载整个页面)
XMLHttp是ajax的基础,ajax封装的就是它的功能,所以了解了XMLHttp,就能更好的使用ajax,更能够对前台如何向后台发起请求有直观的了解(因为你能看到很多请求、响应状态的参数,和许多它的属性及方法,如若灵活使用,必能如臂使指)。
XMLHttp是什么,可以说它是一套API,提供了客户端到http服务器端通讯的协议。客户端可以通过XMLHttp对象向http服务器端发送请求,并用DOM(document object model文档对象模型)来接受处理响应。
那剥开这层封装,该怎么用XMLHttp来实现呢,直接看代码:
js代码:
//这个是创建XMLHttp对象的方法,独立到所有方法之外,每次向后台请求时被调用
function createXMLHttp(){
var XMLHttp = null;
//因为浏览器不同使用的请求对象也不同,所以要判断到底该用那种请求对象
//IE7+, Firefox, Chrome, Opera, Safari 浏览器
if(window.XMLHttpRequest){
XMLHttp = new XMLHttpRequest();
}else{
//IE6, IE5 浏览器
XMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return XMLHttp;
}
//有了XMLHttp对象以后,就可以通过它进行对后台的请求了
function list(){
var XMLHttp = createXMLHttp();
//见名识意,这是XMLHttp的‘当状态改变时’触发的函数,那么如果状态不变,自然不会触发它
XMLHttp.onreadystatechange = function(){
//readyState是XMLHttp的状态,代表客户端这边对于请求这件事做到了哪一部分了
//status是服务端返回给客户端的状态,告知客户端咱们之间的接下来还要做什么
//这两种属性,我会在文末全部列举出来,便于参考记忆
if(XMLHttp.readyState == 4 && XMLHttp.status == 200){
//这里写的就是响应回来后,前台需要进行的操作
//html代码见下面
var target = document.getElementById("divv");
//响应信息放在responseText里,是个字符串
//innerHTML设置或者返回元素的内容
target.innerHTML = XMLHttp.responseText;
}
}
/* 创建一个新的http请求,参数为请求类型(post/get),请求的地址(url),是否同步(async)
XMLHttp.open(method,url,async);
发送请求到http服务器并接收回应,send()里可以放string类型,仅用于post请求的方式
XMLHttp.send();
注意:如果使用的是同步(async那里是false),就不要写onreadystatechange()方法了,直接将后续代码写在send()后面
*/
//如果用get的方式,想要传的参数,直接放到url后面,send()里就不用放东西了
XMLHttp.open("get","/list?userName=YHY&pwd=123",true);
XMLHttp.send();
//如果用post的方式,参数写在send()里,注意是string类型
XMLHttp.open("post","/list",true);
//单独指定请求的某个http头,post方式需要。如果post不传值,可不写该方法
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//如果传值,写在这里,如果不传值,里面为空
XMLHttp.send("userName=YHY&pwd=123");
}
html代码:
<body>
<button onclick="list();">点击我提交</button>
<div id="divv">效果看这里</div>
</body>
点击效果为:div里面的"效果看这里",变更为了从后台获取过来的数据,注意是"变更"而不是"追加",如果想达到追加的效果,如下:(看起来像不像字符串追加)
var target = document.getElementById("divv");
target.innerHTML = target.innerText + "新值放这里";
以上,如果服务器响应回来的,是个字符串,那么并无不可;但如果想用js的ajax获取对象的集合呢?响应回来的json怎么解析? 还用上述办法没问题,只不过显示到用户眼前的就是个json数组了,都是这样的:
[{"id":1,"userName":"YHY","pwd":"123"},
{"id":2,"userName":"WK","pwd":"234"},
{"id":3,"userName":"LYJ","pwd":"456"}
...
]
可以利用eval()方法:
var lists = eval("(" + XMLHttp.responseText +")");
for(var i = 0; i < lists.length; i++){
alert(lists[i].userName);
}
结果为:分别得到YHY、WK、LYJ,效果达到。
以上讲述了js的ajax如何向后台请求、传值,分为get和post两种方式讲解;以及得到后台的响应后怎么处理携带回来的数据,分为字符串和json两种形式讲解;以及如何实现追加功能。
那么后台怎么写呢?其实和使用jquery的ajax相同:
//如果返回的是字符串
@RequestMapping("/list")
public void list(HttpServletResponse response){
response.setCharacterEncoding("UTF-8");
try{
response.getWriter().print("我是要传回去的字符串");
}catch(IOException e){
e.printStackTrace();
}
}
//如果返回的是json
@ResponseBody
@RequestMapping("/list")
public List<User> list(){
List<User> list = new ArrayList<User>();
list.add(new User(1,"YHY","123"));
list.add(new User(2,"WK","234"));
list.add(new User(3,"LYJ","456"));
return list;
}
本篇只是讲述了js的ajax简单的使用方法,要想灵活使用,还要在工作中实践才行......
接下来贴出那密密麻麻的状态值,小伙伴们对其中一部分应该很熟悉的:
XMLHttp的readyState值
0:请求未初始化(还没有调用 open())
1:请求已经建立,但是还没有发送(还没有调用 send())
2:请求已发送,正在处理中(通常现在可以从响应中获取内容头)
3:请求在处理中;通常响应中已有部分数据可用了,但是服务器还没有完成响应的生成
4:响应已完成;您可以获取并使用服务器的响应了
XMLHttp的status值
100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本
200——交易成功
201——提示知道新文件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204——请求收到,但返回信息为空
205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206——服务器已经完成了部分用户的GET请求
300——请求的资源可在多处得到
301——删除请求数据
302——在其他地址发现了请求数据
303——建议客户访问其他URL或访问方式
304——客户端已经执行了GET,但文件未变化
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307——申明请求的资源临时性删除
400——错误请求,如语法错误
401——请求授权失败
402——保留有效ChargeTo头响应
403——请求不允许
404——没有发现文件、查询或URl
405——用户在Request-Line字段定义的方法不允许
406——根据用户发送的Accept拖,请求资源不可访问
407——类似401,用户必须首先在代理服务器上得到授权
408——客户端没有在用户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且无进一步的参考地址
411——服务器拒绝用户定义的Content-Length属性请求
412——一个或多个请求头字段在当前请求中错误
413——请求的资源大于服务器允许的大小
414——请求的资源URL长于服务器允许的长度
415——请求资源不支持请求项目格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请 求也不包含If-Range请求头字段
417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求
500——服务器产生内部错误
501——服务器不支持请求的函数
502——服务器暂时不可用,有时是为了防止发生系统过载
503——服务器过载或暂停维修
504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长 505——服务器不支持或拒绝支请求头中指定的HTTP版本
1xx:信息响应类,表示接收到请求并且继续处理
2xx:处理成功响应类,表示动作被成功接收、理解和接受
3xx:重定向响应类,为了完成指定的动作,必须接受进一步处理
4xx:客户端错误,客户请求包含语法错误或者是不能正确执行
5xx:服务端错误,服务器不能正确执行一个正确的请求
XMLHttp对象的属性与方法
属性:*表示此属性是W3C文档对象模型的扩展.
onreadystatechange* 指定当readyState属性改变时的事件处理句柄,只写
readyState 返回当前请求的状态,只读
responseBody 将回应信息正文以unsigned byte数组形式返回,只读
responseStream 以Ado Stream对象的形式返回响应信息,只读
responseText 将响应信息作为字符串返回,只读
responseXML 将响应信息格式化为Xml Document对象并返回,只读
status 返回当前请求的http状态码,只读
statusText 返回当前请求的响应行状态,只读
方法:
abort 取消当前请求
getAllResponseHeaders 获取响应的所有http头
getResponseHeader 从响应信息中获取指定的http头
open 创建一个新的http请求,并指定此请求的方法、URL以及 验证信息(用户名/密码)
send 发送请求到http服务器并接收回应
setRequestHeader 单独指定请求的某个http头
参考博客
https://blog.csdn.net/qq_38238041/article/details/82914404 小伙伴们可以依据本篇原理,自行封装ajax,既对ajax的学习有帮助,又对js的封装有很大借鉴作用
http://www.w3school.com.cn/jsref/jsref_eval.asp 对于eval()方法的阐述