axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端
json-server
可能很多人并不会写后端,也可能没有一个可以用的后端接口地址
没关系,咱们自己造一个
json-server就是一个可以快速在json文件的基础上,起六个增删改改查查的六个接口
使用json-server先简单起一个服务
npm i -g json-server
db.json
{
"users": [
{
"id": 1,
"name": "枫枫",
"age": 21,
"addr": "湖南省长沙市"
},
{
"id": 2,
"name": "张三",
"age": 22,
"addr": "四川省成都市"
}
]
}
运行服务
json-server -w db.json
# 增
POST http://localhost:3000/users
{
"name": "枫枫",
"age": 22,
"addr": "湖南省长沙市"
}
## id自动增长
# 删
DELETE http://localhost:3000/users/3
# 改 全字段更新,不传就删除
PUT http://localhost:3000/users/3
{
"name": "枫枫1",
"age": 22
}
# 改 单字段更新,传什么更什么
PATCH http://localhost:3000/users/3
{
"name": "枫枫2",
}
# 查列表
GET http://localhost:3000/users
# 查详情
GET http://localhost:3000/users/1
axios使用
html模式
很多人可能也不会用vue的脚手架,没关系,会新建html就行了
<!doctype html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>Axios使用</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
axios.get("http://localhost:3000/users").then(res => {
console.log(res.data)
})
</script>
</body>
</html>
打开控制台就能看到列表的json里面的数据了
后面的一些操作都是通用的
vue3项目中使用
npm init vue@latest

注意:本教程只是讲解axios,所以没勾vue-router和pinia
安装axois
npm i axios
<template>
</template>
<script setup lang="ts">
import axios from "axios";
axios.get("http://localhost:3000/users").then(res => {
console.log(res.data)
})
</script>
axios增删改查
<template>
<div>
<table>
<thead>
<tr>
<th>id</th>
<th>用户名</th>
<th>年龄</th>
<th>地址</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in data.list" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
<td>{{ item.addr }}</td>
<td>
<button @click="detailData(item.id as number)">详情</button>
<button @click="putData(item)">修改</button>
<button @click="deleteData(item)">删除</button>
</td>
</tr>
</tbody>
</table>
<button @click="create">新增一条</button>
</div>
</template>
<script setup lang="ts">
import axios from "axios";
import {reactive} from "vue";
import type {AxiosResponse} from "axios";
const url: string = "http://localhost:3000/users/"
interface jsonData {
readonly id?: number
name: string
age: number
addr?: string
}
interface Data {
list: jsonData[]
}
const data = reactive<Data>({
list: []
})
// 请求列表
async function getData() {
let res: AxiosResponse<jsonData[]> = await axios.get(url)
data.list = res.data
}
// 增加数据
async function create() {
let body: jsonData = {
name: "王五",
age: 23,
addr: "北京市",
}
let res = await axios.post(url, body)
console.log("新增", res.data)
getData()
}
// 修改数据 年龄++ 名字+?
async function putData(item: jsonData){
item.age ++
item.name += "?"
let res = await axios.put(url + item.id, item)
console.log("修改", res.data)
}
// 删除数据
async function deleteData(item: jsonData){
let res = await axios.delete(url + item.id)
console.log("删除", res.data)
getData()
}
// 获取详情
async function detailData(id: number){
let res = await axios.get(url + id)
console.log("详情", res.data)
}
getData()
</script>
axios.get(url, config)
axios.delete(url, config)
axios.post(url, data, config)
axios.put(url, data, config)
axios.patch(url, data, config)
data就是js里面的对象
config
{
// `url` 是用于请求的服务器 URL
url: '/user',
// `method` 是创建请求时使用的方法
method: 'get', // 默认值
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/',
// `transformRequest` 允许在向服务器发送前,修改请求数据
// 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
// 你可以修改请求头。
transformRequest: [function (data, headers) {
// 对发送的 data 进行任意转换处理
return data;
}],
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对接收的 data 进行任意转换处理
return data;
}],
// 自定义请求头
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `params` 是与请求一起发送的 URL 参数
// 必须是一个简单对象或 URLSearchParams 对象
params: {
ID: 12345
},
// `paramsSerializer`是可选方法,主要用于序列化`params`
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// `data` 是作为请求体被发送的数据
// 仅适用 'PUT', 'POST', 'DELETE 和 'PATCH' 请求方法
// 在没有设置 `transformRequest` 时,则必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属: FormData, File, Blob
// - Node 专属: Stream, Buffer
data: {
firstName: 'Fred'
},
// 发送请求体数据的可选语法
// 请求方式 post
// 只有 value 会被发送,key 则不会
data: 'Country=Brasil&City=Belo Horizonte',
// `timeout` 指定请求超时的毫秒数。
// 如果请求时间超过 `timeout` 的值,则请求会被中断
timeout: 1000, // 默认值是 `0` (永不超时)
// `withCredentials` 表示跨域请求时是否需要使用凭证
withCredentials: false, // default
// `adapter` 允许自定义处理请求,这使测试更加容易。
// 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。
adapter: function (config) {
/* ... */
},
// `auth` HTTP Basic Auth
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// `responseType` 表示浏览器将要响应的数据类型
// 选项包括: 'arraybuffer', 'document', 'json', 'text', 'stream'
// 浏览器专属:'blob'
responseType: 'json', // 默认值
// `responseEncoding` 表示用于解码响应的编码 (Node.js 专属)
// 注意:忽略 `responseType` 的值为 'stream',或者是客户端请求
// Note: Ignored for `responseType` of 'stream' or client-side requests
responseEncoding: 'utf8', // 默认值
// `xsrfCookieName` 是 xsrf token 的值,被用作 cookie 的名称
xsrfCookieName: 'XSRF-TOKEN', // 默认值
// `xsrfHeaderName` 是带有 xsrf token 值的http 请求头名称
xsrfHeaderName: 'X-XSRF-TOKEN', // 默认值
// `onUploadProgress` 允许为上传处理进度事件
// 浏览器专属
onUploadProgress: function (progressEvent) {
// 处理原生进度事件
},
// `onDownloadProgress` 允许为下载处理进度事件
// 浏览器专属
onDownloadProgress: function (progressEvent) {
// 处理原生进度事件
},
// `maxContentLength` 定义了node.js中允许的HTTP响应内容的最大字节数
maxContentLength: 2000,
// `maxBodyLength`(仅Node)定义允许的http请求内容的最大字节数
maxBodyLength: 2000,
// `validateStatus` 定义了对于给定的 HTTP状态码是 resolve 还是 reject promise。
// 如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),
// 则promise 将会 resolved,否则是 rejected。
validateStatus: function (status) {
return status >= 200 && status < 300; // 默认值
},
// `maxRedirects` 定义了在node.js中要遵循的最大重定向数。
// 如果设置为0,则不会进行重定向
maxRedirects: 5, // 默认值
// `socketPath` 定义了在node.js中使用的UNIX套接字。
// e.g. '/var/run/docker.sock' 发送请求到 docker 守护进程。
// 只能指定 `socketPath` 或 `proxy` 。
// 若都指定,这使用 `socketPath` 。
socketPath: null, // default
// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
// and https requests, respectively, in node.js. This allows options to be added like
// `keepAlive` that are not enabled by default.
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// `proxy` 定义了代理服务器的主机名,端口和协议。
// 您可以使用常规的`http_proxy` 和 `https_proxy` 环境变量。
// 使用 `false` 可以禁用代理功能,同时环境变量也会被忽略。
// `auth`表示应使用HTTP Basic auth连接到代理,并且提供凭据。
// 这将设置一个 `Proxy-Authorization` 请求头,它会覆盖 `headers` 中已存在的自定义 `Proxy-Authorization` 请求头。
// 如果代理服务器使用 HTTPS,则必须设置 protocol 为`https`
proxy: {
protocol: 'https',
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// see https://axios-http.com/zh/docs/cancellation
cancelToken: new CancelToken(function (cancel) {
}),
// `decompress` indicates whether or not the response body should be decompressed
// automatically. If set to `true` will also remove the 'content-encoding' header
// from the responses objects of all decompressed responses
// - Node only (XHR cannot turn off decompression)
decompress: true // 默认值
}
常用的config
<script setup lang="ts">
import axios from "axios";
axios.get("/users", {
baseURL: "http://localhost:3000", // 设置绝对地址
transformRequest: [function (data, headers) {
console.log("transformRequest", data, headers)
return data
}], // 可以在这里处理请求的数据
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对接收的 data 进行任意转换处理
// console.log("transformResponse", data)
return JSON.parse(data);
}],
headers: {'Content-Type': 'application/json', "xxx": "xxx"},
params: {
xxx123: "xxx123"
},
timeout: 130, // 超时时间 单位毫秒 默认0 不超时
auth: {
username: 'root',
password: 'root'
},
responseType: 'json', // 默认值
}).then(res => {
console.log(res.data)
})
</script>
auth的编码规则
Basic base64encode(username:password)
axios实例
一般对接一个后端接口,上面的写法完全够用了
但是有些项目,前端需要对接几个后端接口,这个时候api接口地址完全不同,有时候响应也是五花八门
所以就需要创建一个实例,一个实例去对接一个api接口
<template>
</template>
<script setup lang="ts">
import axios from "axios";
const blogServerUrl = "http://localhost:3000"
const videoServerUrl = "http://localhost:3001"
const blogAxios = axios.create({
baseURL: blogServerUrl,
headers: {
"Content-Type": "application/json"
},
timeout: 1000,
})
const videoAxios = axios.create({
baseURL: videoServerUrl,
headers: {
"Content-Type": "application/json"
},
timeout: 1000
})
blogAxios.get("users").then(res => {
console.log("博客服务", res.data)
})
videoAxios.get("users").then(res => {
console.log("视频服务", res.data)
})
</script>
axios拦截器
这个算是axios中最有用的
在请求拦截器里面加用户认证
在响应拦截器里面判断后端错误,取数据
<template>
</template>
<script setup lang="ts">
import axios from "axios";
const blogAxios = axios.create({
baseURL: "http://localhost:3000",
headers: {
"Content-Type": "application/json"
},
timeout: 1000,
})
// 请求中间件
blogAxios.interceptors.request.use(function (config) {
config.headers["token"] = "token123"
return config
})
// 响应中间件
blogAxios.interceptors.response.use(function (response){
if (response.status === 200){
// 还可以再这里全局判断这个请求是不是正常的
return response.data
}
console.log(response.statusText)
return Promise.reject(response.statusText);
}, function (error){
// 超出 2xx 范围的状态码都会触发该函数。 一般是后端服务出错了
// 对响应错误做点什么
console.log(error)
return Promise.reject(error);
})
blogAxios.get("users").then(res => {
console.log("博客服务", res)
})
</script>
axios拦截器可以应用在axios主体上,还可以应用到axios实例上
如果是给主体加拦截器,实例是不会有的,反之亦然
axios默认值
全局 axios 默认值
axios.defaults.baseURL = "http://localhost:30001"
axios.defaults.headers["xxx"] = "xxx"
axios.defaults.headers.post["xxx1"] = "xxx1" // 只是post请求才有
实例默认值
// 创建实例时配置默认值
const instance = axios.create({
baseURL: 'http://localhost:3000'
});
// 创建实例后修改默认值
instance.defaults.headers.common['Authorization'] = "xxx";
优先级
当前请求的配置 > 实例的默认值 > 全局默认值
错误处理
then模式
<script setup lang="ts">
import axios from "axios";
axios.get("http://localhost:30001/users").then(res => {
console.log("博客服务", res)
}).catch(function (err) {
console.log("出错了", err)
})
</script>
async模式
<script setup lang="ts">
import axios from "axios";
async function getData(){
try {
let res = await axios.get("http://localhost:3000/users")
console.log("博客服务", res)
}catch (err){
console.log("出错了", err)
}
}
getData()
</script>
文件上传
后端以go语言为例
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"path"
)
func Cors() gin.HandlerFunc {
return func(context *gin.Context) {
method := context.Request.Method
context.Header("Access-Control-Allow-Origin", "*")
context.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token, x-token")
context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PATCH, PUT")
context.Header("Access-Control-Expose-Headers", "*")
context.Header("Access-Control-Allow-Credentials", "true")
if method == "OPTIONS" {
context.AbortWithStatus(http.StatusNoContent)
}
}
}
func upload(c *gin.Context) {
fileHead, err := c.FormFile("file")
if err != nil {
c.JSON(200, gin.H{"code": 7, "msg": "参数错误"})
return
}
savePath := path.Join("uploads", fileHead.Filename)
err = c.SaveUploadedFile(fileHead, savePath)
if err != nil {
fmt.Println(err)
c.JSON(200, gin.H{"code": 7, "msg": "上传失败"})
return
}
c.JSON(200, gin.H{"code": 0, "data": savePath, "msg": "上传成功"})
}
func main() {
router := gin.Default()
router.Use(Cors()) // 跨域
router.POST("upload", upload)
router.Run(":8080")
}

使用axios进行文件上传,都是固定的写法
- 获取
input标签中的file - 构造
FormData - 发请求
<template>
<div>
<input type="file" name="file" id="upload" @change="upload">
</div>
</template>
<script setup lang="ts">
import axios from "axios";
function upload(e: Event) {
const target = e.target;
if (target instanceof HTMLInputElement) {
const files = target.files;
if (files) {
const formData = new FormData()
for (let i = 0; i < files.length; i++) {
formData.append('file', files[i])
}
axios.post("http://localhost:8080/upload", formData, {headers: {token: "xxx"}}).then(res => {
console.log(res)
})
}
}
}
</script>
上传进度
axios.post("http://localhost:8080/upload", formData, {
headers: {token: "xxx"},
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
const progress = Math.round((progressEvent.loaded / (progressEvent.total as number)) * 100)
console.log('上传进度:' + progress + '%')
}
}).then(res => {
console.log(res)
})
取消上传
<template>
<div>
<input type="file" name="file" id="upload" @change="upload">
<button @click="cancel">取消上传</button>
</div>
</template>
<script setup lang="ts">
import axios from "axios";
import type {Canceler, AxiosProgressEvent} from "axios";
const cancelToken = axios.CancelToken;
let cancelCtl : Canceler;
function upload(e: Event) {
const target = e.target;
if (target instanceof HTMLInputElement) {
const files = target.files;
if (files) {
const formData = new FormData()
for (let i = 0; i < files.length; i++) {
formData.append('file', files[i])
}
axios.post("http://localhost:8080/upload", formData, {
// 重新生成一个
cancelToken: new cancelToken(function executor(c: Canceler) {
cancelCtl = c
}),
headers: {token: "xxx"},
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
const progress = Math.round((progressEvent.loaded / (progressEvent.total as number)) * 100)
console.log('上传进度:' + progress + '%')
}
}).then(res => {
console.log(res)
})
}
}
}
function cancel() {
cancelCtl('取消上传')
}
</script>
文件下载
后端以go语言为例
func download(c *gin.Context) {
name := "厉害了.jpg"
c.Header("Content-Type", "application/octet-stream") // 表示是文件流,唤起浏览器下载,一般设置了这个,就要设置文件名
c.Header("Content-Disposition", "attachment; filename="+name) // 用来指定下载下来的文件名,让浏览器认的
c.Header("Content-Transfer-Encoding", "binary") // 表示传输过程中的编码形
filename := url.QueryEscape(name)
c.Header("filename", filename) // 让前端认的
c.File("uploads/5.jpg")
}
前端部分也是通用的
- 设置
responseType: 'blob' - 构造blob
- 模拟a标签点击
- 移除a标签
function download() {
axios.get("http://localhost:8080/download", {
responseType: 'blob',
}).then(res => {
console.log(res.headers)
if (res && res.status === 200) {
const {data, headers} = res
// 解析文件名
let fileName = decodeURIComponent(headers["filename"])
// 此处当返回json文件时需要先对data进行JSON.stringify处理,其他类型文件不用做处理
const blob = new Blob([data], {type: headers['Content-Type'] as string})
// 创建a标签
let dom = document.createElement('a')
let url = window.URL.createObjectURL(blob)
dom.href = url
dom.download = decodeURI(fileName)
dom.style.display = 'none'
document.body.appendChild(dom)
dom.click()
// 删除a标签
if (dom.parentNode) {
(dom.parentNode as Node).removeChild(dom);
}
window.URL.revokeObjectURL(url);
}
})
}
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端
json-server
可能很多人并不会写后端,也可能没有一个可以用的后端接口地址
没关系,咱们自己造一个
json-server就是一个可以快速在json文件的基础上,起六个增删改改查查的六个接口
使用json-server先简单起一个服务
npm i -g json-server
db.json
{
"users": [
{
"id": 1,
"name": "枫枫",
"age": 21,
"addr": "湖南省长沙市"
},
{
"id": 2,
"name": "张三",
"age": 22,
"addr": "四川省成都市"
}
]
}
运行服务
json-server -w db.json
# 增
POST http://localhost:3000/users
{
"name": "枫枫",
"age": 22,
"addr": "湖南省长沙市"
}
## id自动增长
# 删
DELETE http://localhost:3000/users/3
# 改 全字段更新,不传就删除
PUT http://localhost:3000/users/3
{
"name": "枫枫1",
"age": 22
}
# 改 单字段更新,传什么更什么
PATCH http://localhost:3000/users/3
{
"name": "枫枫2",
}
# 查列表
GET http://localhost:3000/users
# 查详情
GET http://localhost:3000/users/1
axios使用
html模式
很多人可能也不会用vue的脚手架,没关系,会新建html就行了
<!doctype html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>Axios使用</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<script>
axios.get("http://localhost:3000/users").then(res => {
console.log(res.data)
})
</script>
</body>
</html>
打开控制台就能看到列表的json里面的数据了
后面的一些操作都是通用的
vue3项目中使用
npm init vue@latest

注意:本教程只是讲解axios,所以没勾vue-router和pinia
安装axois
npm i axios
<template>
</template>
<script setup lang="ts">
import axios from "axios";
axios.get("http://localhost:3000/users").then(res => {
console.log(res.data)
})
</script>
axios增删改查
<template>
<div>
<table>
<thead>
<tr>
<th>id</th>
<th>用户名</th>
<th>年龄</th>
<th>地址</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item in data.list" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
<td>{{ item.addr }}</td>
<td>
<button @click="detailData(item.id as number)">详情</button>
<button @click="putData(item)">修改</button>
<button @click="deleteData(item)">删除</button>
</td>
</tr>
</tbody>
</table>
<button @click="create">新增一条</button>
</div>
</template>
<script setup lang="ts">
import axios from "axios";
import {reactive} from "vue";
import type {AxiosResponse} from "axios";
const url: string = "http://localhost:3000/users/"
interface jsonData {
readonly id?: number
name: string
age: number
addr?: string
}
interface Data {
list: jsonData[]
}
const data = reactive<Data>({
list: []
})
// 请求列表
async function getData() {
let res: AxiosResponse<jsonData[]> = await axios.get(url)
data.list = res.data
}
// 增加数据
async function create() {
let body: jsonData = {
name: "王五",
age: 23,
addr: "北京市",
}
let res = await axios.post(url, body)
console.log("新增", res.data)
getData()
}
// 修改数据 年龄++ 名字+?
async function putData(item: jsonData){
item.age ++
item.name += "?"
let res = await axios.put(url + item.id, item)
console.log("修改", res.data)
}
// 删除数据
async function deleteData(item: jsonData){
let res = await axios.delete(url + item.id)
console.log("删除", res.data)
getData()
}
// 获取详情
async function detailData(id: number){
let res = await axios.get(url + id)
console.log("详情", res.data)
}
getData()
</script>
axios.get(url, config)
axios.delete(url, config)
axios.post(url, data, config)
axios.put(url, data, config)
axios.patch(url, data, config)
data就是js里面的对象
config
{
// `url` 是用于请求的服务器 URL
url: '/user',
// `method` 是创建请求时使用的方法
method: 'get', // 默认值
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
baseURL: 'https://some-domain.com/api/',
// `transformRequest` 允许在向服务器发送前,修改请求数据
// 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
// 你可以修改请求头。
transformRequest: [function (data, headers) {
// 对发送的 data 进行任意转换处理
return data;
}],
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对接收的 data 进行任意转换处理
return data;
}],
// 自定义请求头
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `params` 是与请求一起发送的 URL 参数
// 必须是一个简单对象或 URLSearchParams 对象
params: {
ID: 12345
},
// `paramsSerializer`是可选方法,主要用于序列化`params`
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// `data` 是作为请求体被发送的数据
// 仅适用 'PUT', 'POST', 'DELETE 和 'PATCH' 请求方法
// 在没有设置 `transformRequest` 时,则必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属: FormData, File, Blob
// - Node 专属: Stream, Buffer
data: {
firstName: 'Fred'
},
// 发送请求体数据的可选语法
// 请求方式 post
// 只有 value 会被发送,key 则不会
data: 'Country=Brasil&City=Belo Horizonte',
// `timeout` 指定请求超时的毫秒数。
// 如果请求时间超过 `timeout` 的值,则请求会被中断
timeout: 1000, // 默认值是 `0` (永不超时)
// `withCredentials` 表示跨域请求时是否需要使用凭证
withCredentials: false, // default
// `adapter` 允许自定义处理请求,这使测试更加容易。
// 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。
adapter: function (config) {
/* ... */
},
// `auth` HTTP Basic Auth
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// `responseType` 表示浏览器将要响应的数据类型
// 选项包括: 'arraybuffer', 'document', 'json', 'text', 'stream'
// 浏览器专属:'blob'
responseType: 'json', // 默认值
// `responseEncoding` 表示用于解码响应的编码 (Node.js 专属)
// 注意:忽略 `responseType` 的值为 'stream',或者是客户端请求
// Note: Ignored for `responseType` of 'stream' or client-side requests
responseEncoding: 'utf8', // 默认值
// `xsrfCookieName` 是 xsrf token 的值,被用作 cookie 的名称
xsrfCookieName: 'XSRF-TOKEN', // 默认值
// `xsrfHeaderName` 是带有 xsrf token 值的http 请求头名称
xsrfHeaderName: 'X-XSRF-TOKEN', // 默认值
// `onUploadProgress` 允许为上传处理进度事件
// 浏览器专属
onUploadProgress: function (progressEvent) {
// 处理原生进度事件
},
// `onDownloadProgress` 允许为下载处理进度事件
// 浏览器专属
onDownloadProgress: function (progressEvent) {
// 处理原生进度事件
},
// `maxContentLength` 定义了node.js中允许的HTTP响应内容的最大字节数
maxContentLength: 2000,
// `maxBodyLength`(仅Node)定义允许的http请求内容的最大字节数
maxBodyLength: 2000,
// `validateStatus` 定义了对于给定的 HTTP状态码是 resolve 还是 reject promise。
// 如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),
// 则promise 将会 resolved,否则是 rejected。
validateStatus: function (status) {
return status >= 200 && status < 300; // 默认值
},
// `maxRedirects` 定义了在node.js中要遵循的最大重定向数。
// 如果设置为0,则不会进行重定向
maxRedirects: 5, // 默认值
// `socketPath` 定义了在node.js中使用的UNIX套接字。
// e.g. '/var/run/docker.sock' 发送请求到 docker 守护进程。
// 只能指定 `socketPath` 或 `proxy` 。
// 若都指定,这使用 `socketPath` 。
socketPath: null, // default
// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
// and https requests, respectively, in node.js. This allows options to be added like
// `keepAlive` that are not enabled by default.
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// `proxy` 定义了代理服务器的主机名,端口和协议。
// 您可以使用常规的`http_proxy` 和 `https_proxy` 环境变量。
// 使用 `false` 可以禁用代理功能,同时环境变量也会被忽略。
// `auth`表示应使用HTTP Basic auth连接到代理,并且提供凭据。
// 这将设置一个 `Proxy-Authorization` 请求头,它会覆盖 `headers` 中已存在的自定义 `Proxy-Authorization` 请求头。
// 如果代理服务器使用 HTTPS,则必须设置 protocol 为`https`
proxy: {
protocol: 'https',
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// see https://axios-http.com/zh/docs/cancellation
cancelToken: new CancelToken(function (cancel) {
}),
// `decompress` indicates whether or not the response body should be decompressed
// automatically. If set to `true` will also remove the 'content-encoding' header
// from the responses objects of all decompressed responses
// - Node only (XHR cannot turn off decompression)
decompress: true // 默认值
}
常用的config
<script setup lang="ts">
import axios from "axios";
axios.get("/users", {
baseURL: "http://localhost:3000", // 设置绝对地址
transformRequest: [function (data, headers) {
console.log("transformRequest", data, headers)
return data
}], // 可以在这里处理请求的数据
// `transformResponse` 在传递给 then/catch 前,允许修改响应数据
transformResponse: [function (data) {
// 对接收的 data 进行任意转换处理
// console.log("transformResponse", data)
return JSON.parse(data);
}],
headers: {'Content-Type': 'application/json', "xxx": "xxx"},
params: {
xxx123: "xxx123"
},
timeout: 130, // 超时时间 单位毫秒 默认0 不超时
auth: {
username: 'root',
password: 'root'
},
responseType: 'json', // 默认值
}).then(res => {
console.log(res.data)
})
</script>
auth的编码规则
Basic base64encode(username:password)
axios实例
一般对接一个后端接口,上面的写法完全够用了
但是有些项目,前端需要对接几个后端接口,这个时候api接口地址完全不同,有时候响应也是五花八门
所以就需要创建一个实例,一个实例去对接一个api接口
<template>
</template>
<script setup lang="ts">
import axios from "axios";
const blogServerUrl = "http://localhost:3000"
const videoServerUrl = "http://localhost:3001"
const blogAxios = axios.create({
baseURL: blogServerUrl,
headers: {
"Content-Type": "application/json"
},
timeout: 1000,
})
const videoAxios = axios.create({
baseURL: videoServerUrl,
headers: {
"Content-Type": "application/json"
},
timeout: 1000
})
blogAxios.get("users").then(res => {
console.log("博客服务", res.data)
})
videoAxios.get("users").then(res => {
console.log("视频服务", res.data)
})
</script>
axios拦截器
这个算是axios中最有用的
在请求拦截器里面加用户认证
在响应拦截器里面判断后端错误,取数据
<template>
</template>
<script setup lang="ts">
import axios from "axios";
const blogAxios = axios.create({
baseURL: "http://localhost:3000",
headers: {
"Content-Type": "application/json"
},
timeout: 1000,
})
// 请求中间件
blogAxios.interceptors.request.use(function (config) {
config.headers["token"] = "token123"
return config
})
// 响应中间件
blogAxios.interceptors.response.use(function (response){
if (response.status === 200){
// 还可以再这里全局判断这个请求是不是正常的
return response.data
}
console.log(response.statusText)
return Promise.reject(response.statusText);
}, function (error){
// 超出 2xx 范围的状态码都会触发该函数。 一般是后端服务出错了
// 对响应错误做点什么
console.log(error)
return Promise.reject(error);
})
blogAxios.get("users").then(res => {
console.log("博客服务", res)
})
</script>
axios拦截器可以应用在axios主体上,还可以应用到axios实例上
如果是给主体加拦截器,实例是不会有的,反之亦然
axios默认值
全局 axios 默认值
axios.defaults.baseURL = "http://localhost:30001"
axios.defaults.headers["xxx"] = "xxx"
axios.defaults.headers.post["xxx1"] = "xxx1" // 只是post请求才有
实例默认值
// 创建实例时配置默认值
const instance = axios.create({
baseURL: 'http://localhost:3000'
});
// 创建实例后修改默认值
instance.defaults.headers.common['Authorization'] = "xxx";
优先级
当前请求的配置 > 实例的默认值 > 全局默认值
错误处理
then模式
<script setup lang="ts">
import axios from "axios";
axios.get("http://localhost:30001/users").then(res => {
console.log("博客服务", res)
}).catch(function (err) {
console.log("出错了", err)
})
</script>
async模式
<script setup lang="ts">
import axios from "axios";
async function getData(){
try {
let res = await axios.get("http://localhost:3000/users")
console.log("博客服务", res)
}catch (err){
console.log("出错了", err)
}
}
getData()
</script>
文件上传
后端以go语言为例
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"path"
)
func Cors() gin.HandlerFunc {
return func(context *gin.Context) {
method := context.Request.Method
context.Header("Access-Control-Allow-Origin", "*")
context.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token, x-token")
context.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PATCH, PUT")
context.Header("Access-Control-Expose-Headers", "*")
context.Header("Access-Control-Allow-Credentials", "true")
if method == "OPTIONS" {
context.AbortWithStatus(http.StatusNoContent)
}
}
}
func upload(c *gin.Context) {
fileHead, err := c.FormFile("file")
if err != nil {
c.JSON(200, gin.H{"code": 7, "msg": "参数错误"})
return
}
savePath := path.Join("uploads", fileHead.Filename)
err = c.SaveUploadedFile(fileHead, savePath)
if err != nil {
fmt.Println(err)
c.JSON(200, gin.H{"code": 7, "msg": "上传失败"})
return
}
c.JSON(200, gin.H{"code": 0, "data": savePath, "msg": "上传成功"})
}
func main() {
router := gin.Default()
router.Use(Cors()) // 跨域
router.POST("upload", upload)
router.Run(":8080")
}

使用axios进行文件上传,都是固定的写法
- 获取
input标签中的file - 构造
FormData - 发请求
<template>
<div>
<input type="file" name="file" id="upload" @change="upload">
</div>
</template>
<script setup lang="ts">
import axios from "axios";
function upload(e: Event) {
const target = e.target;
if (target instanceof HTMLInputElement) {
const files = target.files;
if (files) {
const formData = new FormData()
for (let i = 0; i < files.length; i++) {
formData.append('file', files[i])
}
axios.post("http://localhost:8080/upload", formData, {headers: {token: "xxx"}}).then(res => {
console.log(res)
})
}
}
}
</script>
上传进度
axios.post("http://localhost:8080/upload", formData, {
headers: {token: "xxx"},
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
const progress = Math.round((progressEvent.loaded / (progressEvent.total as number)) * 100)
console.log('上传进度:' + progress + '%')
}
}).then(res => {
console.log(res)
})
取消上传
<template>
<div>
<input type="file" name="file" id="upload" @change="upload">
<button @click="cancel">取消上传</button>
</div>
</template>
<script setup lang="ts">
import axios from "axios";
import type {Canceler, AxiosProgressEvent} from "axios";
const cancelToken = axios.CancelToken;
let cancelCtl : Canceler;
function upload(e: Event) {
const target = e.target;
if (target instanceof HTMLInputElement) {
const files = target.files;
if (files) {
const formData = new FormData()
for (let i = 0; i < files.length; i++) {
formData.append('file', files[i])
}
axios.post("http://localhost:8080/upload", formData, {
// 重新生成一个
cancelToken: new cancelToken(function executor(c: Canceler) {
cancelCtl = c
}),
headers: {token: "xxx"},
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
const progress = Math.round((progressEvent.loaded / (progressEvent.total as number)) * 100)
console.log('上传进度:' + progress + '%')
}
}).then(res => {
console.log(res)
})
}
}
}
function cancel() {
cancelCtl('取消上传')
}
</script>
文件下载
后端以go语言为例
func download(c *gin.Context) {
name := "厉害了.jpg"
c.Header("Content-Type", "application/octet-stream") // 表示是文件流,唤起浏览器下载,一般设置了这个,就要设置文件名
c.Header("Content-Disposition", "attachment; filename="+name) // 用来指定下载下来的文件名,让浏览器认的
c.Header("Content-Transfer-Encoding", "binary") // 表示传输过程中的编码形
filename := url.QueryEscape(name)
c.Header("filename", filename) // 让前端认的
c.File("uploads/5.jpg")
}
前端部分也是通用的
- 设置
responseType: 'blob' - 构造blob
- 模拟a标签点击
- 移除a标签
function download() {
axios.get("http://localhost:8080/download", {
responseType: 'blob',
}).then(res => {
console.log(res.headers)
if (res && res.status === 200) {
const {data, headers} = res
// 解析文件名
let fileName = decodeURIComponent(headers["filename"])
// 此处当返回json文件时需要先对data进行JSON.stringify处理,其他类型文件不用做处理
const blob = new Blob([data], {type: headers['Content-Type'] as string})
// 创建a标签
let dom = document.createElement('a')
let url = window.URL.createObjectURL(blob)
dom.href = url
dom.download = decodeURI(fileName)
dom.style.display = 'none'
document.body.appendChild(dom)
dom.click()
// 删除a标签
if (dom.parentNode) {
(dom.parentNode as Node).removeChild(dom);
}
window.URL.revokeObjectURL(url);
}
})
}