Axios的使用
http说明
前后台请求过程
- 前后应用从浏览器端向服务器发送HTTP请求(请求报文)
- 后台服务器接收到请求后, 调度服务器应用处理请求, 向浏览器端返回HTTP响应(响应报文)
- 浏览器端接收到响应, 解析显示响应体/调用监视回调
请求报文
请求报文
1
2
3
4
5
6
71). url: 可能带GET请求参数
2). method: 请求方式
3). headers: 多个请求头
Host: www.baidu.com
Cookie: BAIDUID=AD3B0FA706E; BIDUPSID=AD3B0FA706;
Content-Type: application/x-www-form-urlencoded
4). body: 请求体仅有POST、PUT以及PATCH这三个动词时会包含请求体,而GET、HEAD、DELETE、CONNECT、TRACE、OPTIONS这几个动词时不包含请求体。
- GET: 从服务器端读取数据
- POST: 向服务器端添加新数据
- PUT: 更新服务器端已经数据
- DELETE: 删除服务器端数据
请求的格式
1
2
3
4
5
6
7
8
9
101). Content-Type: application/x-www-form-urlencoded;charset=utf-8
用于键值对参数,参数的键值用=连接, 参数之间用&连接
例如: name=%E5%B0%8F%E6%98%8E&age=12
2). Content-Type: application/json;charset=utf-8
用于json字符串参数
例如: {"name": "%E5%B0%8F%E6%98%8E", "age": 12}
3). Content-Type: multipart/form-data
用于文件上传请求
请求头
Header | 解释 | 示例 |
---|---|---|
Accept | 指定客户端能够接收的内容类型 | Accept: text/plain, text/html,application/json |
Accept-Charset | 浏览器可以接受的字符编码集。 | Accept-Charset: iso-8859-5 |
Accept-Encoding | 指定浏览器可以支持的web服务器返回内容压缩编码类型。 | Accept-Encoding: compress, gzip |
Accept-Language | 浏览器可接受的语言 | Accept-Language: en,zh |
Accept-Ranges | 可以请求网页实体的一个或者多个子范围字段 | Accept-Ranges: bytes |
Authorization | HTTP授权的授权证书 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Cache-Control | 指定请求和响应遵循的缓存机制 | Cache-Control: no-cache |
Connection | 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) | Connection: close |
Cookie | HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 | Cookie: $Version=1; Skin=new; |
Content-Length | 请求的内容长度 | Content-Length: 348 |
Content-Type | 请求的与实体对应的MIME信息 | Content-Type: application/x-www-form-urlencoded |
Date | 请求发送的日期和时间 | Date: Tue, 15 Nov 2010 08:12:31 GMT |
Expect | 请求的特定的服务器行为 | Expect: 100-continue |
From | 发出请求的用户的Email | From: user@email.com |
Host | 指定请求的服务器的域名和端口号 | Host: www.zcmhi.com |
If-Match | 只有请求内容与实体相匹配才有效 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Modified-Since | 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 | If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
If-None-Match | 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Range | 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag | If-Range: “737060cd8c284d8af7ad3082f209582d” |
If-Unmodified-Since | 只在实体在指定时间之后未被修改才请求成功 | If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT |
Max-Forwards | 限制信息通过代理和网关传送的时间 | Max-Forwards: 10 |
Pragma | 用来包含实现特定的指令 | Pragma: no-cache |
Proxy-Authorization | 连接到代理的授权证书 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Range | 只请求实体的一部分,指定范围 | Range: bytes=500-999 |
Referer | 先前网页的地址,当前请求网页紧随其后,即来路 | Referer: http://www.zcmhi.com/archives... |
TE | 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 | TE: trailers,deflate;q=0.5 |
Upgrade | 向服务器指定某种传输协议以便服务器进行转换(如果支持) | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
User-Agent | User-Agent的内容包含发出请求的用户信息 | User-Agent: Mozilla/5.0 (Linux; X11) |
Via | 通知中间网关或代理服务器地址,通信协议 | Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1) |
Warning | 关于消息实体的警告信息 | Warn: 199 Miscellaneous warning |
响应报文
1 | 1). 响应状态码: 200/404 |
响应状态码
区间
1
2
3
4
51** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误常见的几个
1
2
3
4
5200 OK 请求成功。一般用于GET与POST请求
201 Created 已创建。成功请求并创建了新的资源
401 Unauthorized 未授权/请求要求用户的身份认证
404 Not Found 服务器无法根据客户端的请求找到资源
500 Internal Server Error 服务器内部错误,无法完成请求
API 分类
REST API:
- 发送请求进行CRUD哪个操作由请求方式来决定
- 同一个请求路径可以进行多个操作
- 请求方式会用到GET/POST/PUT/DELETE
非REST API:
- 请求方式不决定请求的CRUD操作
- 一个请求路径只对应一个操作
- 一般只有GET/POST
环境安装
NodeJs
1 | # 安装 NVM |
json-server
- 用来快速搭建REST API的工具包 : https://github.com/typicode/json-server
- 下载:
npm install -g json-server
- 目标根目录下创建数据库json文件: db.json
1 | { |
启动服务器
执行命令:
json-server --watch db.json
浏览器测试访问
1
2
3
4
5
6http://localhost:3000/posts
http://localhost:3000/posts/1
# 结果
GET /posts 304 5.540 ms - -
GET /posts/1 304 3.355 ms - -
其他测试接口
什么是axios
Axios是一个开源的可以用在浏览器端和NodeJS的异步通信框架,主要作用就是实现AJAX异步通信,功能特点如下:
- 从浏览器中创建 XMLHttpRequests
- 从node.js创建请求
- 支持Promise API
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 XSRF (跨站请求伪造)
为什么使用axios
由于Vue.js是一个视图层框架,作者严格遵循SOC(关注度分离原则),所以Vue.js并不包含AJAX的通信功能,为了能解决通信问题,作者单独开发了 vue-resource的插件,不过在2.0版本以后停止了对该插件的维护,并推荐了Axios框架。
初体验
axios 和Vue-axios
vue项目中,有些代码使用了 vue-axios和axios
1
2
3
4
5import Vue from "vue";
import axios from "axios";
import VueAxios from "vue-axios";
Vue.use(VueAxios, axios);vue-axios
只是帮你在axios
上面再封装了一层,让axios
可以直接和Vue
组装起来。推荐使用axios
安装 axios
命令如下:
1
2
3npm install --save axios
# 使用 cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
axios 引入
在项目中的main.js中引入axios模块
在vue的原型上定义一个属性,等于这个axios,因为组件都继承Vue原型对象
所以在任意组件使用
this.$http
就相当于使用了axios1
2
3import axios from "axios";
//修改内部http为axios
Vue.prototype.$http = axios;
axios基本使用
发送get 请求
1
2
3
4
5
6axios.get('http://localhost:3000/posts').then(function(ret){
# 拿到 ret 是一个对象 所有的对象都存在 ret 的data 属性里面
// 注意data属性是固定的用法,用于获取后台的实际数据
// console.log(ret.data)
console.log(ret)
})get 请求传递参数
1 | # 通过传统的url 以 ? 的形式传递参数 |
- delete 请求传参,传参的形式和 get 请求一样
1 | // axios.delete('http://localhost:3000/comments/4') |
post 请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 配置post请求的content-type
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
# 通过选项传递参数
axios.post('http://localhost:3000/axios', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
# 通过 URLSearchParams 传递参数
var params = new URLSearchParams();
params.append('uname', 'zhangsan');
params.append('pwd', '111');
axios.post('http://localhost:3000/axios', params).then(function(ret){
console.log(ret.data)
})put (更新操作)请求,传参和 post 请求一样
1
2
3
4
5
6
7
8
9
10// axios.put('http://localhost:3000/comments/4', {body: 'yyy', postId: 1})
axios
.put("http://localhost:3000/axios/123", {
uname: "lisi",
pwd: 123,
})
.then(function (ret) {
console.log(ret.data);
});
axios全局配置
可以在main.js中配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14//配置公共的请求头
axios.defaults.baseURL = "https://127.0.0.1:3000";
// 配置超时时间
axios.defaults.timeout = 3000;
// 配置公共请求头
axios.defaults.headers.common["Authorization"] = AUTH_TOKEN;
//配置公共的post的Content-Type
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded";
// post请求头
axios.defaults.headers.post["Content-Type"] =
"application/x-www-form-urlencoded;charset=UTF-8";
// 请求的时候自动携带cookie
axios.defaults.withCredentials = true;
使用全局示例
启动
json-server --watch db.json
main.js引入axios
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import Vue from "vue";
import App from "./App";
import router from "./router";
import axios from "axios";
// 环境的切换:通过node的环境变量来匹配我们的默认的接口url前缀
if (process.env.NODE_ENV == "development") {
axios.defaults.baseURL = "http://localhost:3000";
} else if (process.env.NODE_ENV == "debug") {
axios.defaults.baseURL = "https://www.ceshi.com";
} else if (process.env.NODE_ENV == "production") {
axios.defaults.baseURL = "https://www.production.com";
}
//修改内部http为axios
Vue.prototype.$http = axios;router\index.js
中配置路由,让首页显示Home组件。1
2
3
4
5
6
7
8
9
10
11
12
13import Vue from "vue";
import Router from "vue-router";
import Home from "@/components/Home";
Vue.use(Router);
export default new Router({
// mode: 'history',
routes: [
{ path: "/", redirect: "/home" },
{ path: "/home", name: "Home", component: Home },
],
});Home.vue组件,请求所有数据显示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34<template>
<div>
<p> 欢迎进入我的网站 </p><br>
{{posts}}
</div>
</template>
<script>
export default {
name: "Home",
data(){
return{
posts:[]
}
},
methods:{
},
created() {
this.$http.get('/posts').then(res=>{
console.log(res)
this.posts=res.data
})
.catch(err=>{
console.log(err)
})
}
}
</script>
<style scoped>
</style>页面可以正常显示查询的结果。
跨域说明
如果是其他的服务器会出现跨域问题,json-server是支持跨域的
查看响应头
Access-Control-Allow-Origin: http://127.0.0.1:8080
浏览器判断跨域为简单请求时候,会在Request Header中添加 Origin (协议 + 域名 + 端口)字段 , 它表示我们的请求源,CORS服务端会将该字段作为跨源标志。
CORS接收到此次请求后 , 首先会判断Origin是否在允许源(由服务端决定)范围之内,如果验证通过,服务端会在Response Header 添加 Access-Control-Allow-Origin、Access-Control-Allow-Credentials等字段。
必须字段:
Access-Control-Allow-Origin
·:表示服务端允许的请求源,*
标识任何外域,多个源,
分隔可选字段
Access-Control-Allow-Credentials
: 表示是否允许发送Cookie,- 设置为true同时,ajax请求设置
withCredentials = true
,浏览器的cookie就能发送到服务端 - 服务端设置如果是
'supportsCredentials' => false,
,表示不允许携带信息头,也会出现跨域问题
Access-Control-Expose-Headers
:调用getResponseHeader()方法时候,能从header中获 取的参数- 设置为true同时,ajax请求设置
浏览器收到Respnose后会判断自己的源是否存在 Access-Control-Allow-Origin允许源中,如果不存在,会抛出“同源检测异常”。
总结:简单请求只需要CORS服务端在接受到携带Origin字段的跨域请求后,在response header中添加Access-Control-Allow-Origin等字段给浏览器做同源判断。
async 和await
async
作为一个关键字放在函数前边,任何一个async
函数都会隐式返回一个promise
;await
关键字只能在使用async
定义的函数中使用,await
后面可以直接跟一个Promise
实例对象,await 函数不能单独使用
;async/await让异步代码看起来,表现更象同代码;
1 | # 1. async 基础用法 |
axios简单封装
测试链接:https://api-hmugo-web.itheima.net/api/public/v1/home/floordata
axios.get()
方法和axios.post()
在提交数据时参数的书写方式还是有区别的。- get的第二个参数是一个{},然后这个对象的params属性值是一个参数对象的。
- 而post的第二个参数就是一个参数对象。两者略微的区别要留意哦!
封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55import axios from "axios";
const instance=axios.create({
//这里是接口公共的url部分,会拼接在url参数前面
baseURL:"https://api-hmugo-web.itheima.net/api/public/v1",
timeout:5000,
})
## 封装get请求
/**
* get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
import QS from 'qs';
export function get(url, params){
return new Promise((resolve, reject) =>{
axios.get(url, {
params: params
}).then(res => {
resolve(res.data);
}).catch(err =>{
reject(err.data)
})
});}
## 封装post请求
## post方法必须要使用对提交从参数对象进行序列化的操作,所以这里我们通过node的qs模块来序列化我们的参数。
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
export function post(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, QS.stringify(params))
.then(res => {
resolve(res.data);
})
.catch(err =>{
reject(err.data)
})
});
}
## 封装del请求
export function del(url){
return instance.get(url);
}
## 封装put请求
export function put(url,data){
return instance.put(url,data);
}调用
1
2
3get("/home/floordata", {}).then((res) => {
console.log(res);
});
axios全局拦截
请求拦截
请求发送拦截,所有的网络请求都会先走这个use方法,我们可以在它里面为请求添加一些自定义的内容
- 比如 config 中的一些信息不符合服务器要求
- 比如每次发送网路请求时,希望在界面显示一个请求图标
- 某些网站请求,必须携带一些特殊的信息(token)
//请求发送拦截,把数据发送给后台之前做些什么...... axios.interceptors.request.use( (request) => { //这个例子中data是loginName和password let REQUEST_DATA = request.data; //统一进行qs模块转换,将对象序列化成URL的形式,以&进行拼接。 //JSON.stringify(ObjectDemo)是将对象转换为json字符串 request.data = qs.stringify(REQUEST_DATA); //再发送给后台 return request; }, function (error) { // Do something with request error return Promise.reject(error); }, );