1 Ajax基础
在了解Ajax之前,先来看看前端开发的演变吧。
前端开发的演变
-
静态网页阶段
这个阶段的网页没有数据交互,所有的前端数据都由后端生成、维护,前端只负责纯粹的展示功能。如果需要更新页面内容,必须重新加载整个网页。
带来的问题是:当我们只希望更新页面中一小部分的内容时,会因为重载网页而对页面中的所有资源也重新加载一遍,不仅用户体验不友好,还增加了服务器的负担。
-
Ajax 阶段
为了解决上述问题,在 2004 年诞生了 Ajax 技术,让页面的局部刷新成为了可能,从而改变了前端开发,使得前端不仅仅是展示页面,还可以管理数据并与用户互动。
Ajax 技术指的是脚本独立向服务器请求数据,拿到数据以后,进行处理并更新网页。整个过程中,后端只是负责提供数据,其他事情都由前端处理,实现了 “获取数据 → 处理数据 → 展示数据” 的完整业务逻辑。
Ajax简介
Ajax 的全称是 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML),是一种用于创建动态网页的技术。
Ajax 是一种使用现有标准的新方法,通过与服务器进行少量的数据交换,Ajax 可以使网页实现异步更新,这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
总结一下上面几行字,中心思想便是Ajax 的出现让网页的整体变得舒适流畅,这点将会在后面的内容中不断体现出来,这儿划一个重点的额关键词——异步。
Ajax的工作原理
接下来来张正儿八经的知识点的图。在用户界面和服务器之间加上一个Ajax引擎,便是实现异步的关键点。
Ajax的一个例子
这里就用“勾诶斯”来实例化一个简单的Ajax吧。
function AjaxRequest(){
//实例化一个Ajax对象(经典new对象)
var xhr = XMLHttpRequest();
//open方法,后面细讲
xhr.open("GET","某个url",true)
//将请求发到服务器去,跟open一起用
xhr.send();
//这里做两个简单判断,一是看访问进程,二是看访问结果
xhr.onreadystatechange = function(){
// 当 readyState 等于 4 且状态为正常时,表示响应已就绪
if (xhr.readyState === 4) {
alert("流程给走完了");
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
alert("访问也没啥问题");
}
}
}
}
Ajax的优缺点
Ajax 的优点:
- 最大的优点是页面无刷新更新,用户的体验非常好;
- 使用异步方式与服务器通信,具有更迅速的响应能力;
- 可以将一些服务器工作转移到客户端,利用客户端资源来处理,减轻服务器和带宽的压力,节约空间和带宽租用成本;
- 技术标准化,并被浏览器广泛支持,不需要下载插件或者小程序;
- Ajax 可使因特网应用程序更小、更快、更友好。
Ajax 的缺点:
- Ajax 不支持浏览器 back 返回按钮;
- 有安全问题,Ajax 暴露了与服务器交互的细节;
- 对搜索引擎不友好;
- 破坏了程序的异常机制;
- 不容易调试。
以上都是网上找的说法,优点的中心思想快,方便,节约空间、兼容性高,缺点的话就是不太安全,偶尔也不太稳定,但是写代码嘛,找bug才是快乐源泉呐。
Ajax核心技术介绍
上面的例子其实也就把Ajax和核心部分大致地体现出来了,接下来我们就一行一行代码的看看。
XMLHttpRequest()
这玩意儿其实就是个类,那么对面向对象有那么一丁点儿感觉的应该都知道,第一件要做的事儿就是先去实例化一下这个对象。毕竟是前端的东西,浏览器几经更迭,自然有些许跟不上时代的节奏。
但好在,IE7以后就都没问题了,但为了严谨,也为了使用方便,这儿就直接给大家整个可以兼容的代码,以后实例化直接拿去用就完事儿。
// 三元表达式,其中问号前面的是条件,当条件是正确的就执行冒号前面的语句,否则执行冒号后面的语句
var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
open()方法
实例化的工作已经结束了,那我们用啥子东西去找这个服务器诶,open()就来了。
解析:xhr.open(method, url, async)
-
method:
-
- 第一个参数用于指定 HTTP 请求的方法,不区分大小写;
- 该参数可取的值包括:“GET”、“POST”、“HEAD”、“PUT”、“OPTIONS”、“DELETE”,其中,“GET” 和 “POST” 是得到广泛支持的请求方法;
-
url:
-
- 第二个参数用于指定 HTTP 请求的 URL 地址,可以是 绝对URL 或 相对URL;
- 绝对URL:需要满足 “同源策略”(服务器明确允许跨域请求的情况除外);
- 相对URL:即相对于文档的 URL;
-
async:
-
- 第三个参数是可选的,可用布尔值指定脚本是否以异步的方式调用此次 Ajax 请求;
- 该参数默认为 true,表示异步调用此次 Ajax 请求,不阻塞后续脚本的执行;
前两个参数应该没啥问题,在很多地方都有,第三个参数的话便是之前说的Ajax的核心,即是否异步处理这一块儿,后面等几行代码都说完了再来说一下这个。
send()方法
既然都已经访问到了服务器,那还不得传点儿东西东西过去?总不能占着茅坑不拉屎嘛。这时候send()方法就出现了。
大家都是上流社会的人,GET和POST的区别不会不知道吧。
简单举个🌰。
var xhr = new XMLHttpRequest();
xhr.open("GET", "某个url");
// 无请求主体
xhr.send(null);
**代码解析:**由于 GET 请求 绝对 没有请求主体,所以在调用 send 方法时可以传递 null 或 省略这个参数;
var xhr = new XMLHttpRequest();
xhr.open("POST", "某个url");
// 把 msg 作为请求主体发送
xhr.send(msg);
代码解析:
- POST 请求通常都拥有请求主体,可在 send 方法中指定它;
- POST 请求的请求主体,应该匹配setRequestHeader方法所指定的 “Content-Type” 头。
服务器什么时候理(响应)我们呢?
我们把东西扔给服务器了,服务器总得给个信儿吧,或者说我们得了解一下物流信息吧。
这里就需要用到XMLHttpRequest这个里面一个经典的属性值readyState。
readyState的值会从0—1—2—3—4地变化。
- 0:初始值,表示请求未初始化,
open
方法尚未调用; - 1:启动请求,open 方法已经调用,但尚未调用 send 方法;
- 2:请求发送,已经调用 send 方法,但尚未接收到响应;
- 3:接收响应,已经接受到部分响应数据,主要是响应头;
- 4:HTTP 响应完成,已经接收到全部响应数据,而且可以在客户端使用。
所以其实只有当readyState的值变成4的时候,我们才能认为服务器给我们整明白了。
那么兄弟萌,是不是readyState的值成了4就说明这个过程完全没问题了呢?当然不是,我们在前面的例子中的最后有一个小小的判断,还判断了一个值——status。
status反映了HTTP 状态码,是用来表示网页服务器响应状态的 3 位数字代码,所有状态码的第一个数字代表了响应的五种状态之一:
- 1xx:临时响应
- 2xx:成功
- 3xx:重定向
- 4xx:请求错误
- 5xx:服务器错误
当status的值控制在200以内或者是304的话,基本上就没啥问题,恭喜通关,如果是其他的值的话估计就快乐不起来了。
拿什么型号的箱子来装我们收到的东西呢?
responseText属性以字符串的形式存储了响应主体,即:服务器的响应数据。
又来举个🌰(HTML 文本)
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
// 当响应成功,获取响应数据,将数据赋值给本地
oView.innerHTML = xhr.responseText;
}
};
xhr.open("GET", "某个url");
xhr.send();
再来举个🌰(JSON 数据)
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
// 使用JSON.parse把 响应数据转换为json数据
var res = JSON.parse(xhr.responseText);
// 将响应数据中的date属性赋值给oTime做内容
oTime.innerText = res.date;
}
};
xhr.open("GET", "某个url");
xhr.send();
**扩展(一些不那么重要的东西):**实际上,响应主体有时还可以从XMLHttpRequest
对象的response
、responseXML
属性获取,它们的使用相对不频繁。
- responseText:无论返回的数据类型是什么,响应主体的内容都会保存在
responseText
属性中; - responseXML:只对 XML 数据有效,若响应主体是非 XML 数据,该属性值为
null
; - response:通常配合
responseType
使用。若指定了XMLHttpRequest
实例的responseType
属性,则将响应内容转换为该属性所指定的格式并返回,否则按默认情况处理。
最后一个🌰(response 与 responseType 的使用)
var xhr = new XMLHttpRequest();
// 指定响应主体的数据格式为 json
xhr.responseType = "json";
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
oTime.innerText = xhr.response.date;
}
};
xhr.open("GET", "某个url");
xhr.send();
**值得注意的是:**若指定了responseType
的值为非 “text” 或 非空最后一个🌰,则responseText
属性就会失效,因此时的响应主体已不再是 “text” 文本形式,继续使用它获取响应主体浏览器会给出相应的报错信息,可自行尝试。
然后再給老板们介绍一个小玩意儿——abort(中止访问)
var xhr = new XMLHttpRequest();
var timer = null; // 用于存储定时器标识
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
clearTimeout(timer); // 未超时则取消定时器
}
};
xhr.open("GET", "/statics/demosource/demo_get_json.php");
xhr.send();
// 2秒后中止此次 GET 请求
timer = setTimeout(function(){
xhr.abort();
}, 2000)
至此差不多哈,有关于Ajax的的那点儿用法大家都应该有个初步的了解了,让我们回到最开始的那个问题,关于open方法的第三个三参数,我如果头铁一定要整成False呢?
也不是不行,也不是不行哈。
简单来说的话就是可以少到判断readyState属性值的步骤,意味着我们了解不到服务器的态度,把send的东西全都堵在了等 直到 HTTP 请求完成完成后再整,也就是所谓的同步请求。
emmmmm…
懂得都懂。
最后给各位上流人士整个jQuery的Ajax代码,请老板们以后写这点儿代码的时候旁边一定要来整个高脚杯。
// 使用jQuery发起ajax请求
$.ajax("/statics/demosource/demo_get_json.php", {
//请求类型
type: "GET",
//要发送的数据
data: {
country: country,
city: city
},
//数据格式
dataType: "json",
//请求成功后执行
success: function (res) { // res为响应成功返回的数据
oIpt_country.innerText = res.params.country;
oIpt_city.innerText = res.params.city;
},
//请求失败后执行
error: function (res) { // 这里的res为响应失败返回的数据
alert("请求失败:" + res.status);
}
});
拜了个拜。