Axios

^_^ 基本介绍

  • Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
  • 应用场景: 像VUE、react、Node等项目。
  • 评价: 可以说axios把请求这件事做到了极致,封装的很好用,除了低版IE外,浏览器的支持性很好。
    在Vue1.x中,官方推荐使用的ajax库是vue-resource。到了Vue2.x,官方(尤大)推荐的ajax库改为了Axios,其说法是因为已有一个更完备的轮子,就不需要造一个新的。
  • 下载:
    使用npm: npm i axios
    使用cdn: <script src=“https://unpkg.com/axios/dist/axios.min.js”>
同类比对
  • ajax:
    优点:局部更新;原生支持
    缺点:嵌套回调
  • jqueryAjax:
    在原生的ajax的基础上进行了封装;支持jsonp
  • fetch:
    优点:解决回调地狱
    缺点:API 偏底层,需要封装;默认不带Cookie,需要手动添加; 浏览器支持情况不是很友好,需要第三方的ployfill
  • axios:
    直呼666.



^_^ 配置对象

小栗子:

let configObj = {
  method: 'get',
  url: 'https://www.baidu.com/s',
  params: {
    is: 'UTF-8',
    wd: 'axios',
  },
}

axios(configObj).then(res => {
  console.log(res)
}).catch(rej => {
  console.warn(rej)
})

说明:
以上发送的get请求,请求地址:https://www.baidu.com/s?ie=UTF-8&wd=axios
以例可见 配置对象 是axios的主要内容 和 请求的本质。

请求配置 的 常用属性

  • method:

指定请求方法,默认为get请求。

  • baseURL:

将自动加在 url 前面,除非 url 是一个绝对 URL。
一般用在 axios实例中 作为提取 请求地址的公共部分使用。

  • url:

请求地址,可以在其后面直接写请求参数,也可以在下面的params中写。

  • params:

get请求的 请求参数,将与请求一起发送的 URL 参数。
params必须是一个无格式对象(plain object),所谓的无格式的对象就是属性值皆为字符串的对象

  • paramsSerializer:

是一个负责 params 序列化的函数,什么时候 params 需要序列化?
当params不是一个 无格式对象的时候,就需要序列化,否则无法拼接在url后面。

  paramsSerializer: function(params) {
   return Qs.stringify(params, {indices: false})
  },  

当params的属性值为一个数组时,就不再是无格式对象了:
params = {ids: [1, 2, 3]}

  1. qs.stringify({ids: [1, 2, 3]}, { indices: false })
    序列化之后: ids=1&ids=2&id=3
  2. qs.stringify({ids: [1, 2, 3]}, {arrayFormat: ‘indices‘})
    序列化之后:ids[0]=1&aids1]=2&ids[2]=3
  3. qs.stringify({ids: [1, 2, 3]}, {arrayFormat: ‘brackets‘})
    序列化之后:ids[]=1&ids[]=2&ids[]=3
  4. qs.stringify({ids: [1, 2, 3]}, {arrayFormat: ‘repeat‘})
    序列化之后:ids=1&ids=2&id=3
  • data:

post、put、patch 请求的 请求体。
Vue使用axios请求数据,默认post请求传参是json格式,若需要formData格式,如此操作:

// 安装axios时,qs也被axios裹挟安装了
import qs from 'qs'     
let reqObj = {...}
let formDataObj = qs.stringify(reqObj)

let configObj = {
    data: formDataObj,
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
}

多说一嘴,curl 的 POST的 -d 的请求体 默认的是 formData格式。

  • transformRequest:

在向服务器发送前,修改post、put、patch 请求的 请求体.
建议用在 axios实例中 作为提取 请求地址的公共部分使用。

let configObj = {
    transformRequest: [function (data) {
    // 对 data 进行任意转换处理  
    ......
    // 必须将处理后的 结果 送出来
    // 且 返回的结果 必须一个字符串,或 ArrayBuffer,或 Stream  
    return JSON.stringify(data); 
    }],

    // 经过 transformRequest 加工,data从对象变成了字符串,  
    // 所以在请求头中说一下 这个 字符串 其本质 是 一个 json对象。
    headers: {
      'Content-Type': 'application/json',
    }
}
  • transformResponse:

在 响应数据 传递给 then/catch 前,可以在此 进行修改.
在这里获取的 数据,是后台传过来的res.data数据(响应体中的数据),
且是 数据是 原始类型,即 json字符串,
为什么在then中获取到的确实res.data 是对象类型,
这是因为 axios 内部给自动解析处理,这点也就是作者说的特性之一:自动转换json数据。
像 fetch 请求 就需要手动 将后端传过来的json字符串解析成对象

let configObj = {
  method: 'post',
  transformResponse: [function (responseData){
    let data = JSON.parse(responseData)
    data.name= 'wtt'
    return data
  }],
}
  • timeout:

指定请求超时的毫秒数 (0 表示无超时时间)
如果请求话费了超过 timeout 的时间,请求将被中断

  • headers:

配置请求报文的 请求头 对象。
通过 请求头 传递 token, 可以在请求头中自定义一个Token字段

let configObj = {
    headers: {
      'Token': '123123123'
    }
}

来,大概了解一下请求头相关 字段

  • Accept: 浏览器可以接收的内容类型
  • Content-Type:请求体中的内容的mime类型。
  • Accept-Charset:浏览器能识别的字符集
  • Accept-Encoding:浏览器可以处理的编码方式
  • Accept-Language:浏览器接收的语言
  • Authorization:: HTTP 基础验证,并提供凭据
  • Cache-Control::指示缓存系统应该怎样处理缓存
  • Connection:告诉服务器使用怎样的连接方式。有keep-alive和close。
  • Cookie::发送请求时发送cookie
  • Content-Length:一个请求的请求体的内存长度,单位为字节(byte)。
  • Content-MD5:使用base64进行了编码的请求体的MD5校验
  • Date:发送请求时的GMT时间。
  • Referer:指当前请求的 来自。
  • User-Agent:通常就是用户的浏览器相关信息。
  • Via:用来记录一个请求经过了哪些代理或网关才被送到目标服务器上。
  • auth

是 HTTP 基础验证,并提供凭据,
该处的设置,会覆写掉用 headers 设置的自定义 Authorization
在这里主要写一些验证相关的信息,例如 token,token写在这里 显得 专业,
如果像上面非要在 header中 自定义一个 Token字段也可以 但是要和 后端的同学 说一下。

let configObj = {
    auth: {
      'token': '123123123'
    }
}

vue 项目中使用axios 的 跨域 配置

  • 跨域问题 是由于 浏览器 本身的一种安全机制所导致的,也就是说只用浏览器和服务器之间会存在 跨域 的问题,注意 本机测试 跨域问题,即使是localhost也要带上 http 前缀,否则 浏览器不会发出请求 。
  • jsonp 是解决 跨域问题的一种方案,利于标签的scr属性不受跨域限制的特性(凡是拥有”src”这个属性的 标签 都拥有跨域的能力,比如script、img)。
  • 代理 是解决 跨域的另一种方案。
    原理解释:上面说过 只有 浏览器发出的请求 存在这跨域的问题,也就是说 服务器 和 服务器 之间是没有跨域的概念(如果服务器没有设置禁止跨域的权限问题), 可以相互请求数据, 因此 配置一个代理的服务器 去请求 目标服务器中的数据,然后再把请求的响应数据返回给客户端,这样就可以实现跨域访问数据。

对于axios而言,只能使用get和post方法来进行请求数据,不同通过标签的src属性进行数据访问,所以axios 解决跨域的方案只能是 使用代理了。

Talking is cheap, show me the code!:

  1. 在vue根目录下创建: vue.config.js文件,在项目编译 的时候 这个文件会和 隐藏起来的那一大堆vue create 项目初始化形成的配置文件 自动进行合并、覆盖。
  2. 在配置文件中写入 代理
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://qqfwwx.tidaizhe.cn:8036',  //后端服务器域名
        changeOrigin: true,  //是否跨域 
        pathRewrite: {
          '^/api': ' '  //正则匹配 /api  =>路径重写
        }
      }
    },
  }
}
  1. 更改 axios 的 baseURL

原先:

axios({
  baseUrl: ' http://qqfwwx.tidaizhe.cn:8036/bbb/ ',
  url: ' /aaa ',
})

更改之后:

axios({
  baseUrl: ' /api/bbb/ ',
  url: ' /aaa ',
})
  1. 重新跑一下项目(只要是动了 vue.config.js中的内容)

说明:
并不是说,如果设置了代理,axios发送的每个请求就必须都得使用代理,
不是这样的,如果我们有些请求不想使用代理 发送请求,
就想在本地服务器的url下 发出请求,那么就不写含有代理意义的 /api 的字段,
请求的url 原先怎么写就怎么写就可以了。



^_^ axios 的常用 API

  • 【1】为方便使用,axios为所有支持的请求方法提供了 别名api

axios(url[, config]) 默认使get请求
axios.get(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.delete(url[, config])
axios.patch(url[, data[, config]])
说明:
使用别名时url、method、data 这三个属性 不必出现在 配置对象 中。

  • 【2】请求并发api

处理并发请求的助手函数: axios.all(); axios.spread()

let axios = require('axios')

let configObj111 = {
  method: 'post',
  url: 'https://jsonplaceholder.typicode.com/posts',
  data: {
    a: 11111,
  },
}

let configObj222 = {
  method: 'post',
  url: 'https://jsonplaceholder.typicode.com/posts',
  data: {
    a: 22222,
  },
}

axios.all([
  axios(configObj1),
  axios(configObj2),
]).then(axios.spread((res1,res2) => {
  console.log(res1.data,111111)
  console.log(res2.data,222222)
}))
  • 【3】创建请求实例api

请求实例最大的价值就是 给众多 请求 按照 公共域名后缀 进行分类处理,
抽离每一类的公共部分 作为 请求实例 的内容。

// 抽离一类请求的公共配置
let publicConfig = {
  baseURL: 'http://www.baidu.com/api',
  timeout: 5000,
}
let axiosInstance = axios.create(publicConfig)

let configObj = {
  method: 'get',
  url: '/aaa/bbb',
  params: {
    name: 'tom',
  },
}
axiosInstance(configObj).then(res => {
  console.log(res)
})
为了方便操作,请求实例 也为支持请求的方法提供了 别名api

axiosInstance.get(url[, config])
axiosInstance.post(url[, data[, config]])
axiosInstance.put(url[, data[, config]])
axiosInstance.delete(url[, config])
axiosInstance.patch(url[, data[, config]])

栗子:

let publicConfigObj = {
  baseURL: 'https://jsonplaceholder.typicode.com',
}
let instance = axios.create(publicConfigObj)

const configObj = {
  timeout: 5000,
}
let data={name: 'wtt'}

instance.post('/posts', data, configObj).then(res => {
  console.log(res)
}).catch(rej => {
  console.warn(rej)
})

注意: 请求实例 的请求 不要用 并发相关的api

  • 【4】 全局 默认值

通过 axios 的 defaults 属性 设置全体 axios 的公共配置

let axios = require('axios')
axios.defaults.baseURL = 'https://api.example.com';

说明:
请求实例 也是可以 通过 defaults 属性 设置 实例默认值的,但是很少用。

配置 的 优先级

具体请求 的 配置对象 的优先级 最大
请求实例 的 配置对象 的优先级 其次
全局默认值 的 优先级 最小

  • 【5】 拦截器

请求实例 也可以 设置拦截器。

  1. 请求拦截器
// use 两个参数函数:
// 第一个: 请求成功
// 第二个: 请求失败
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    ......
    return config; // 放行
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});

说明:
前面在介绍 配置对象 时 有提到 transformRequest,注意区分,
transformRequest 是数据拦截,其的权限 仅是 对于 请求体 数据的修改,
而这里的 请求拦截 是对本次请求 的更改,直白的说 可以修改 配置对象

栗子:

let axios = require('axios')
// 这里我 只用 第一个参函数
axios.interceptors.request.use(function (config) {
  // 修改 配置对象
  if (config.timeout < 100) {
    console.log("时间太短了吧,干脆别请求了")
    let rej = "给 catch 说, 我把请求取消了"
    return Promise.reject(rej) // 可简写: throw rej
  } else {
    console.log("时间这还差不多,我再改一下时间 就更好玩了")
    config.timeout = 65535
    return config
  }
});

let arr1 = 'https://jsonplaceholder.typicode.com/posts'
let arr2 = { a:1111 }
let arr3 = { timeout: 20 }

axios.post(arr1, arr2, arr3).then(res => {
  console.log(res.config,'then 捕获到的')
}).catch(rej => {
  console.warn(rej,'catch 捕获到的')
})

/* 输出:
时间太短了吧,干脆别请求了
给 catch 说, 我把请求取消了 catch 捕获到的
*/
  1. 响应拦截器

上面 请求拦截 里面的相关说明,这里一样适用。

axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;  // 放行
}, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
});

栗子:

let axios = require('axios')

axios.interceptors.response.use(function (res) {
  if (res.status == 200) {
    let ok = "给 then 说,请求成功了"
    return ok
  } else {
    let fail = "给 catch 说,请求失败了"
    throw fail
  }
});

let arr1 = 'https://jsonplaceholder.typicode.com/posts'
let arr2 = {a: 123}

axios.post(arr1, arr2).then(res => {
  console.log(res,'then 捕获到的')
}).catch(rej => {
  console.warn(rej,'catch 捕获到的')
})
/* 输出:
当 res.status == 200的输出: 给 then 说,请求成功了  then 捕获到的

当 res.status != 200的输出: 给 catch 说,请求失败了  catch 捕获到的
*/



^_^ axios 请求返回 的 数据结构

// 由5部分构成
{
  // 响应体的数据
  data: {},

  // 状态码
  status: 200,

  // 状态信息
  statusText: 'OK',

  // 响应头
  headers: {},

  // 请求 的 配置对象
  config: {}
}



^_^ 项目中 axios模块封装

  • request.js
import axios frim 'axios'

axios.defaults.btimeout = 6666

// 根据项目 需要 设置 请求拦截器 和 响应拦截器

export const instance111 = axios.create({
  baseURL: "http://www.baidu.com/aaa"  
})

export const instance222 = axios.create({
  baseURL: "http://www.baidu.com/BBB"  
})
  • home.vue
import {instance111} from "./request.js"

function getRequest(configObj) {
  instance111(configObj).then(res => {
    console.log(res)
  }).catch(rej => {
    console.log(rej)
  })
}

说明:
如果 请求过多 可以 将请求 抽离 出一个 home.js文件。



^_^ axios 上传文件

<template>
    <input type="file" @change="Upload" />
</template>
<script>
import axios from "axios";

export default {
  methods: {
    	Upload(event) {
     	 let file = event.target.files[0];
     	 // 在这里进行一系列的校验
      	let formData = new FormData();
     	 formData.append("avatar", file);
     	 formData.append("name", "wtt");

     	 axios.post("http://localhost:8090/upload", formData, {
        	  "Content-type": "multipart/form-data",
   	     })
      	  .then(res => {
         	 console.log(res)
       	 });
    },
  },
};
</script>

FormData 类

上面axios上传文件时,把文件数据放到了 FormData实例中,下面说以下js中的FormData 类 的基本用法。
FormData可以将form表单元素的name与value进行组合(var formData=new FormData(form);),实现表单数据的序列化,从而简化表单元素的拼接,提高工作效率。

  • FormData.append()
    向 FormData 中添加新的属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值。
  • FormData.set()
    给 FormData 设置属性值,如果FormData 对应的属性值存在则覆盖原值,否则新增一项属性值
  • FormData.get()
    返回在 FormData 对象中与给定键关联的第一个值
  • FormData.getAll()
    返回一个包含 FormData 对象中与给定键关联的所有值的数组。
  • FormData.delete()
    从FormData对象里面删除一个键值对
  • FormData.has()
    返回一个布尔值表明 FormData 对象是否包含某些键
  • FormData.keys()
    返回一个包含所有键的iterator对象 ,通过 for…of 查看返回的数据
  • FormData.values()
    返回一个包含所有值的iterator对象 ,通过 for…of 查看返回的数据
  • FormData.entries()
    返回一个包含所有键值对的iterator对象,通过 for…of 查看返回的数据

^_^ axios 下载文件

		// 响应式显示 下载进度
        let finish = ref(0)
        // 文件下载-----------------------------
        const videoDownloadLocal = (url) => {
            let downLoadFileName = "自定义下载的文件名.mp4";
            axios({
                method: "get",
                url,
                // 必须显式指明响应类型是一个Blob对象,这样生成二进制的数据,才能通过window.URL.createObjectURL进行创建成功
                responseType: "blob",

                // 过程事件监听
                onDownloadProgress(e) {
                    let percent = Math.floor(100 * (e.loaded / e.total));
                    console.warn(percent)
                    finish.value = percent
                },
            }).then((res) => {
                if (!res) {
                    return;
                }
                console.log(res);
                // 将lob对象转换为域名结合式的url
                let blobUrl = window.URL.createObjectURL(res.data);
                let link = document.createElement("a");
                document.body.appendChild(link);
                link.style.display = "none";
                link.href = blobUrl;
                // 设置a标签的下载属性,设置文件名及格式,后缀名最好让后端在数据格式中返回
                link.download = downLoadFileName;
                // 自触发click事件
                link.click();
                document.body.removeChild(link);
                window.URL.revokeObjectURL(blobUrl);
/*
	至此下载完成-------------------------------------------
*/
             }.catch((rej) => {
					console.error(rej)
				})
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值