背景
在了解ajax之前我们了解到的JavaScript能力是有限的,在学习了ajax之前web平台提供所有的api都只停留在单机的阶段。
这样会造成一些无法实现的功能,例如:
- 无法在实现用户登陆功能时,当用户输入邮箱地址显示对应的头像。
- 无法在实现用户注册功能时,当用户输入邮箱或用户名就提示是否存在。
- 无法在实现留言板功能时,实时看到最新的用户留言。
已知的发送请求的方法
- 地址栏输入地址,回车,刷新。
- 特定元素的href或src属性。
- 表单提交
- 这些方案我们无法通过或者是很难通过代码的方式进行编程操作。
需求
- 对服务端发出请求并接受服务端返回的响应。
- 如果我们可以通过JavaScript直接发送网络请求,那么web就可以坐更多的交互而不仅仅是单机。
ajax
为了解决以上问题ajax应运而生。
- ajax最早出现在2005年的Google Suggest
- 它不是像HTML,JavaScript,CSS这样的一种技术
- 它四在浏览器进行网络编程的技术方案。
- 它使得我们可以通过JavaScript直接获取服务端最新的内容而不必重新加载页面。
- ajax是浏览器提供的一套api,可以通过JavaScript调用,从而实现通过代码控制请求与响应,实现通过JavaScript进行网络编程。
应用场景
- 按需获取数据
- 对用户数据校验
- 自动更新页面内容
- 提升用户体验,无刷新的体验
发送ajax请求的步骤
- 创建XMLHttpRequest类型的对象
- 准备发送,打开与一个网址直接的连接
- 执行发送动作
- 指定xhr状态变化事件处理函数。
//原生ajax
//1.创建一个xmlhttprequest对象
var xhr = new XMLHttpRequest();
// //2.打开一个与网址之间的链接。
xhr.open("GET", "https://jsonplaceholder.typicode.com/users?id=1");
// //3.通过链接发送请求。
xhr.send(null);
// //4.对接受的数据进行操作。也就是指定状态变化事件处理函数
xhr.onreadystatechange = function() {
//通过判断xhr的readyState的状态,确定此次请求是否完成。
if (this.readyState === 4) {
console.log(this.responseText);
}
}
1.XMLHttpRequest类型对象
ajax api中核心提供的是一个XMLHttpRequest类型,所有的ajax操作都需要使用到这个类型。
//1.创建一个xmlhttprequest对象
var xhr = new XMLHttpRequest();
2.open方法开启请求
本质上XMLHttpRequest就是JavaScript在web平台发送HTTP请求的手段,所有我们发送出去的请求仍然是HTTP请求,同样符合HTTP约定的格式。
语法:
xhr.open(method,url);
- method:要使用的HTTP方法,比如GET,POST,PUT,DELETE等等。
- url:需要发起请求的URL地址,字符串格式
3.send方法发送请求
用于发送http请求
语法:
xhr.send(body);
body:在XHR请求中要发送的数据体,根据请求头中的类型进行传参,如果是GET方法无需设置数据体,可以传null或者不传参。
setRequestHeader方法设置请求头
此方法必须在open方法和send方法之间调用。
语法:xhr.setRequestHeader(header,value);
header一般设置Content-Tpye传输数据类型,即服务器需要我们传送的数据类型。
value:具体的数据类型,常用:“application/x-www-form-urlencoded"和"applicaition/json”.
下面是post方法发送请求。
xhr.open("POST", "https://jsonplaceholder.typicode.com/users");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("name=harry&age=19");
xhr.onreadystatechange = function() {
//通过判断xhr的readyState的状态,确定此次请求是否完成。
if (this.readyState === 4) {
console.log(this.responseText);
}
}
4.readyState属性
readyState属性返回一个XMLHttpRequest代理当前所处的状态,由于readystatechange事件是在xhr对象状态变化时触发,也就意味着这个事件会被触发多次。
ajax中的同步与异步
- 同步:一个人在同一时刻只能做一件事情,在执行一些耗时的操作做别的事情只能等待。
- 异步:在执行一些耗时的操作可以去做别的事情,而不是等待。
ajax中的实现
xhr.open方法第三个参数要求传递的是一个boolean值,其作用就是设置此次请求是否采用异步方式执行。默认为true,如果需要同步执行可以通过传递false实现,如果采用同步方式执行,代码会卡死在xhr.send这一步。
//原生ajax
//1.创建一个xmlhttprequest对象
var xhr = new XMLHttpRequest();
// //2.打开一个与网址之间的链接。
xhr.open("GET", "https://jsonplaceholder.typicode.com/users?id=1",false);
// //3.通过链接发送请求。
xhr.send(null);
// //4.对接受的数据进行操作。也就是指定状态变化事件处理函数
xhr.onreadystatechange = function() {
//通过判断xhr的readyState的状态,确定此次请求是否完成。
if (this.readyState === 4) {
console.log(this.responseText);
}
}
按照上面的案例我们设置了同步进行,open方法结束之后进行send方法,由于在此期间我们没有绑定readystagechange方法,所以当send结束之后readystate状态就是最后的4,这样我们当send结束之后先去绑定事件,然后由于已经请求结束,所以readystate状态不会再变,所以不会再触发。
建议
为了让事件可以触发,所以可以在send方法之前注册事件。这样不论是同步还是异步都可以触发成功,所以同步的话程序可能会出现问题所以尽量采用异步。
数据传输格式
XML
一种数据描述手段,由于其数据冗杂太多,操作复杂。所以基本现在的前端项目不会再用了。
<? version="1.0" encoding="utf-8"?>
<booklist>
<book>
<name>
红楼梦
</name>
<author>
曹雪芹
</author>
</book>
</booklist>
<!-- xml就是一种数据格式 -->
<!-- 元数据:用来描述数据的数据-->
<!-- 缺点: -->
<!-- 1.元数据占用的数据量比较大,不利于大量数据的网络传输 -->
<!-- 2.在其他语言中,比如js,解析内部数据时方法比较复杂,不方便使用。 -->
<!-- 数据冗杂太多,同时操作复杂。 -->
JSON
也是一种数据描述手段,类似于JS字面量方式。服务端采用json格式返回数据,客户端按照json格式解析数据。
{
"users": [{
"id": 0,
"name": "bob",
"age": 19
},
{
"id": 1,
"name": "pig",
"age": 20
}
],
"posts": [{
"id": 0,
"userid": 0,
"title": "javaScript",
"content": "js is a good language"
}]
}
JSON对象
- 在js中json对象有两个方法较为常用,一个是parse方法可以把json格式的字符串数据转换成js对象。另一个是stringfy方法可以把js中的对象转换成json字符串。
//json对象
//json对象中有两个方法
//parse可以把json格式的字符串数据转换成js对象。
console.log(JSON.parse(str));
//stringify方法可以把js中的对象转换成json格式的字符串
console.log(JSON.stringify(obj));
不管是json还是xml只是在ajax请求过程中用到,并不代表他们与ajax之间有必然的联系,只是数据协议而已。
不管服务器端是采用xml还是采用json本质上都是将数据返回给客户端。
服务端应该根据响应内容的格式设置一个合理的Content-Type。
GET请求
GET请求获取数据。通常在一次GET请求过程中,参数传递都是通过URL地址中的?参数传递
“https://jsonplaceholder.typicode.com/users?id=1”
以上的url就是筛选id为1的对象。
- 一般在get请求中无需设置请求头。
- 无需设置send方法中的响应体,可以传null或者干脆不传。
完整的get请求
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/users?id=1");
xhr.send();
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
console.log(this.responseText);
}
}
POST请求
- POST请求是添加数据。
- POST请求过程中,都是采用请求体承载需要提供的数据。
- 需要设置请求头中的Content-type,以便于服务端接受数据
- 需要提交到服务端的数据可以通过send方法的参数传递。
POST请求
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:8080");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("name=lily&age=18");
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
console.log(this.responseText); //返回的是新增的数据.
}
}
send方法中可以使用json格式传输。
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://localhost:8080");
//json格式传递
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(`{
"name":"bob",
"age":18}`); //用反引号然后内容按照json格式传输。
//也可以将对象通过json的方法转换成json字符串
xhr.send(JSON.stringify(objt));
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
console.log(this.responseText); //返回的是新增的数据.
}
}
手动封装一个ajax函数
了解封装的过程,一般清空在开发中都是使用第三方提供的AJAX库,因为他们可能更加严谨。为了在后续的开发过程中可以更方便的使用ajax的api,所以一般都是封装到一个函数中以便调用。
// 参数1:请求方式{string}
// 参数2:url地址{string}
//参数3:请求的参数{object}
//参数4:定义回调函数,请求完成后执行的操作。
function ajax(method, url, params, done) {
method = method.toUpperCase();
let xhr = new XMLHttpRequest();
//将对象格式的参数转换成urlencoded格式方便后续请求,
let pairs = [];
for (k in params) {
pairs.push(k + "=" + params[k]);
}
let str = pairs.join("&").toString();
//判断是get方法还是post方法
if (method === "GET") {
url += "?" + str;
}
xhr.open(mehod, url);
var data = null;
if (method === "POST") {
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
data = str;
}
xhr.send(data);
xhr.onreadystatechange = function() {
if (this.readyState !== 4) return;
else {
//执行外部传进来的回调函数
done(JSON.parse(this.responseText));
}
}
}
jQuery中的ajax
jQuery中封装了ajax函数,功能十分广泛。
$.ajax()
- 常用选项参数介绍:
- url:请求地址
- type:请求方法,默认为get
- dataType:服务端响应数据类型
- contentType:请求体内容类型,默认
application/x-www-form-urlencoded
- data:需要传递到服务端的数据,如果GET则通过URL传递,如果POST则听过请求体传递。
- timeout:请求超时时间
- beforeSend:请求发起之前触发
- success:请求成功之后触发(响应状态码200)
- error:请求失败触发
- complete:请求完成触发(不管成功与否)
//ajax方法
//参数是一个配置的对象。
//404 没有请求到数据
//500服务器端出现了错误
//304没有从服务器而是从缓存中获取数据
//200表示数据传输成功可用
$.ajax({
url: "http://localhost:3000/users",
type: "GET",
dataType: "json",
data: {
"name": "bob"
},
beforeSend: function(xhr) {
console.log("开始发送请求");
},
success: function(data) {
console.log(data); //将字符串转换成了对象格式。
},
complete: function(xhr) { //不一定成功
console.log("请求完成");
},
error: function(xhr) {
console.log("请求失败");
}
})
需要注意的是,success里面我们定义的方法参数是json字符串经过转换后的对象,不需要我们再手动用json的方法转换了。
$.get()
get方法通过远程http GET请求载入信息。
语法:$.get(url,data,callback)
- url:请求地址
- data:传递的数据,以对象的形式,表示我们要获取的数据参数。
- callback:回调函数,我们对数据的处理方法。
jQuery中ajax方法实现get请求
$.ajax({
url: "http://localhost:3000/comments",
type: "GET",
dataType: "json",
data: {
"id": 1
},
success: function(data) {
console.log(data);
}
});
采用get方法实现get请求
$.get("http://localhost:3000/comments", {
"id": 1
}, function(data) {
console.log(data);
});
post请求
添加数据
语法:$.post(url,data,callback)
- url:请求地址
- data:传递的数据,以对象的形式,表示我们要添加的数据参数。
- callback:回调函数,我们对数据的处理方法。
jQuery中ajax方法实现post请求
$.ajax({
url: "http://localhost:3000/comments",
type: "POST",
dataType: "json",
data: {
"postid": 12,
"body": "a new comment!"
},
success: function(data) {
console.log(data);
}
});
采用post方法实现post请求
$.post("http://localhost:3000/comments", {
"postid": 13,
"body": "second new comment!"
}, function(data) {
console.log(data);
});
put请求
put请求用于更改数据。
//put请求 更改数据
$.ajax({
url: "http://localhost:3000/comments/1",
type: "put",
dataType: "json",
data: {
"body": "change",
"postid": 1
}, //data数据中会覆盖掉之前的数据,所以根据需求设置data属性。
success: function(data) {
console.log(data);
}
})
delete请求
用于删除指定的数据
$.ajax({
url: "http://localhost:3000/comments/3",
type: "delete",
data: {
"content": "good"
}
})
其他的ajax方法
由于其他的ajax方法不常用所以在这里只介绍一个setup初始化方法,其他的方法可以到官网自行学习。
$.ajaxSetup
方法用于设置全局的参数,这样就可以在后面的请求中不需要写这些参数了。
//其他的ajax方法
//平时不常用
$.ajaxSetup({
url: "http://localhost:3000/comments/1",
type: "GET"
});
//设置了setup之后就不需要再写重复属性了。
$.ajax({
data: {
"name": "bob"
}
});
axios库
axios是目前应用最为广泛的ajax封装库
Axios的使用方式
- 地址:https://unpkg.com/axios/dist/axios.min.js
- 使用script标签引入
Axios API
- 可以通过向axios()传递相关配置来创建请求。
axios(config)
config为对象格式的配置选项,axios(url,config)
config为可选配置。
常用配置项
- url 用于请求的服务器URL,必须写。
- method 创建请求时使用的方法
- baseURL 传递相对URL前缀,将自动加在url前面
- headers 即将被发送的自定义请求头
- params 即将与请求一起发送的URL参数
- data 作为请求主体被发送的数据
- timeout 指定请求超时的毫秒数(0 表示无超时时间)
- responseType 表示服务器响应的数据类型 ,默认“json”。
axios({
url: "/comments",
method: "GET",
baseURL: "http://localhost:3000",
}).then(function(response) {
console.log(response.data);
}).catch(function(error) {
console.log(error);
});
由于axios是基于promise方法,所以通过.then方法来对返回的数据进行操作。axios返回的response有很多内容,一般的我们需要的内容是response的data属性。
全局配置默认值
类似于jQuery中的setup方法,axios中可以直接对axios对象的属性进行设置,以达到设置默认值的作用。
//全局配置默认值
axios.defaults.baseURL = "http://localhost:3000";
axios.defaults.headers.post['Content-Type'] = "application/x-www-urlencoded";
拦截器
在请求或相应被then或者catch处理前拦截他们进行处理。
//使用拦截器对请求进行拦截处理
//对后面的所有axios请求进行拦截。
axios.intercdptors.request.use(function(config) {
config.params = {
"id": 1
}
return config;
})
可以使用拦截器,更改config的参数。
axios中的快速请求
axios中的get请求
//get请求
axios.get("http://localhost:3000/comments"); //直接写url
axios.get("http://localhost:3000/comments", { //可以通过传参来进行特定数据的获取。
params: {
"id": 3
}
}).then(function(response) {
console.log(response.data);
});
axios中的post请求
//post请求
//post请求第二个参数不需要像之前一样填写data可以直接写对象。
axios.post("http://localhost:3000/comments", {
"name": "bob",
"age": 19
}).then(function(response) {
console.log(response.data);
});