1. Ajax概述
1.1 什么是Ajax
AJAX是创建交互式网页应用的网页开发技术的一种。
Ajax = 异步 JavaScript 和 XML 或者是 HTML(标准通用标记语言的子集)。可以用于创建快速动态网页的技术。在无需重新加载整个网页的情况下,能够更新部分网页的技术。通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 Ajax)如果需要更新内容,必须重载整个网页页面。
1.2 Ajax的用途与优点
- 可以显示新的HTML内容而不用向服务器重新请求整个页面
- 能够提交一个表单后立即显示结果
- 用户登录而不用跳转到新的页面
- 遍历数据库信息加载更多而不刷新页面
正是因为这个技术的出现,让web程序每次接发数据时,不用每次都递交整个页面的数据,大大提高了客户端与服务器之间传递数据的速度和效率,
简而言之,Ajax可使因特网应用程序更小、更快,更友好。Ajax最大的优点就是在客户端与服务器交换数据时不用向服务器请求整个页面。
2. 封装Ajax方法
2.1 Ajax请求的五个步骤
- 创建一个异步对象
let xmlhttp = new XMLHttpRequest();
- 设置请求方式和请求地址
xmlhttp.open(type, url, true);
- 发送请求
xmlhttp.send();
- 监听状态的变化
xmlhttp.onreadystatechange = function(){
// 编写相关监听状态的代码
}
- 处理返回结果
if(xmlhttp.readyState === 4){
// 判断是否请求成功
if(xmlhttp.status == 200){
// 5.处理返回的结果
console.log("接收到服务器返回的数据");
}else{
console.log("没有接收到服务器返回的数据");
}
}
2.2 readyState的五种状态详解
状态 | 说明 |
---|---|
(0)未初始化 | 此阶段确认XMLHttpRequest对象是否创建,并为调用open()方法进行未初始化作好准备。值为0表示对象已经存在,否则浏览器会报错--对象不存在。 |
(1)载入 | 此阶段对XMLHttpRequest对象进行初始化,即调用open()方法,根据参数(method,url,true)完成对象状态的设置。并调用send()方法开始向服务端发送请求。值为1表示正在向服务端发送请求。 |
(2)载入完成 | 此阶段接收服务器端的响应数据。但获得的还只是服务端响应的原始数据,并不能直接在客户端使用。值为2表示已经接收完全部响应数据。并为下一阶段对数据解析作好准备。 |
(3)交互 | 此阶段解析接收到的服务器端响应数据。即根据服务器端响应头部返回的MIME类型把数据转换成能通过responseBody、responseText或responseXML属性存取的格式,为在客户端调用作好准备。状态3表示正在解析数据。 |
(4)完成 | 此阶段确认全部数据都已经解析为客户端可用的格式,解析已经完成。值为4表示数据解析完毕,可以通过XMLHttpRequest对象的相应属性取得数据。 |
所有在监听状态栏改变时,只需要当 readyState == 4 时才表示已经完成了,这时再对状态码(status)进行检测,通过百度可以看出,当状态码等于200的时候,表示服务器已经成功处理了请求,我们可以通过这一点来判断服务器是否返回成功,下面来封装一个自己的Ajax方法。
2.3 封装Ajax方法
在前面我们已经了解了 Ajax 请求的5个步骤,我们可以根据这五个步骤来封装Ajax方法。
首先要确定是传递哪些参数:
参数 | 解释 |
---|---|
url | 服务器的地址 |
data | 传向服务器的数据 |
success | 当请求成功后执行的方法 |
error | 当请求失败后执行的方法 |
timeout | 超时时间 |
初步考虑要解决的问题:
- 首先传入的数据是一个对象,而客户服务器之间的数据格式是 **key=value&key=value;**这样的字符串,所以我们首先要将传入的对象转换成 **key=value;**的格式
- 在url中不能出现中文,如果出现了中文是需要转码的
- 兼容性问题,在较低的ie浏览器版本是没有XMLHttpRequest这个对象的
2.4 初步封装代码
function objToStr(obj) {
obj = obj || {
};
for(var key in obj){
// 在URL中是不可以出现中文的, 如果出现了中文需要转码
// 可以调用encodeURIComponent方法
// URL中只可以出现字母/数字/下划线/ASCII码
res.push(encodeURIComponent(key)+"="+encodeURIComponent(obj[key]));
}
return res.join("&");
}
function ajax(url, obj, timeout, success, error) {
// 0.将对象转换为字符串
var str = objToStr(obj); // key=value&key=value;
// 1.创建一个异步对象
var xmlhttp, timer;
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
// 2.设置请求方式和请求地址
/*
method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)
*/
xmlhttp.open("GET", url+"?"+str, true);
// 3.发送请求
xmlhttp.send();
// 4.监听状态的变化
xmlhttp.onreadystatechange = function (ev2) {
/*
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
*/
if(xmlhttp.readyState === 4){
// 清除超时计时器
clearInterval(timer);
// 判断是否请求成功
if(xmlhttp.status == 200){
// 5.处理返回的结果
// console.log("接收到服务器返回的数据");
success(xmlhttp);
}else{
// console.log("没有接收到服务器返回的数据");
error(xmlhttp);
}
}
}
// 判断外界是否传入了超时时间
if(timeout){
timer = setInterval(function () {
console.log("中断请求");
xmlhttp.abort();
clearInterval(timer);
}, timeout);
}
}
当得到上述代码以后,很明显,又出现了新的问题:
- 上述代码只实现了 GET 的请求方式,没有实现 POST请求,我们可以增加一个 type 参数来进行选择
- 加入 type 参数来选择是 get 还是 post 时,考虑单词的大小写都能让程序正确运行
- 在较低的ie浏览器版本,如果刷新时提交的数据没有变化,则不会再次向服务器请求数据,而且取上次请求得到的数据,不能保证数据的实时更新
- 参数过多,如果参数顺序不当会导致出现错误,可以参考jQuery中的Ajax方法,传递一个参数
2.5 最终版代码
function objToStr(data) {
// 如果没有传参, 为了添加随机因子,必须自己创建一个对象
data = data || {
};
data.t = new Date().getTime();
var res = [];
for(var key in data){
// URL中只可以出现字母/数字/下划线/ASCII码
// 在URL中是不可以出现中文的, 如果出现了中文需要转码,
// 可以调用encodeURIComponent方法,对url中出现的中文进行转码
res.push(encodeURIComponent(key)+"="+encodeURIComponent(data[key]));
}
// 调用join方法将数组转化为字符串,并且用 & 符号连接返回给ajax方法
return res.join("&");
}
// 接受的仅仅为一个对象
function ajax(option) {
// 将对象转换为字符串
var str = objToStr(option.data); // key=value&key=value;
// 创建一个异步对象
var xmlhttp, timer;
// 针对ie浏览器的兼容性问题
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
// 设置请求方式和请求地址
/*
method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)
*/
// 将 type 转化为小写来判断
if(option.type.toLowerCase() === "get"){
xmlhttp.open(option.type, option.url+"?"+str, true);
// 发送请求
xmlhttp.send();
}
else if(option.type.toLowerCase() === "post"){
// post请求是将数据放在请求头中
xmlhttp.open(option.type, option.url,true);
// 注意点: 以下代码必须放到open和send之间
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send(str);
}
else{
// 既不是get 也不是post时 提示错误,函数结束执行
console.log("请输入正确的请求方式");
return ;
}
// 4.监听状态的变化
xmlhttp.onreadystatechange = function (ev2) {
/*
监听码对应信息
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
*/
if(xmlhttp.readyState === 4){
// 清除超时计时器
clearInterval(timer);
// 判断是否请求成功
if(xmlhttp.status == 200){
// 5.处理返回的结果
// console.log("接收到服务器返回的数据");
option.success(xmlhttp);
}else{
// console.log("没有接收到服务器返回的数据");
option.error(xmlhttp);
}
}
}
// 判断外界是否传入了超时时间
if(option.timeout){
timer = setInterval(function () {
console.log("中断请求");
xmlhttp.abort();
clearInterval(timer);
}, option.timeout);
}
}
写在最后:
虽然一些框架中都为我们封装好了ajax方法,但是只有我们自己去写这些方法,感受其中的过程,解决途中的问题,才能真正提高我们的代码能力,在用这些方法的同时知道其中的原理。对我们了解这个知识点也更加有帮助。
转载:https://blog.csdn.net/Mr_changxin/article/details/115384401