vue--axios的总结及项目中的常见封装方法。
前言
我们知道 vue 2.0版本开始推荐使用 axios 来完成前端 ajax 请求,axios 是一个基于Promise 的 http 库,可以用在浏览器和 node.js 中,axios 成为vue全家桶的一个重要部分,对前后端接口请求起着必不可少的作用,本文主要总结一下 axios 的一些小知识点和项目中常见的需要封装的方法。
正文
1.axios 是什么?
axios 是一个基于 Promise 的 http 库,可以用于浏览器和 node.js 中,在浏览器中创建 XMLHttpRequest 对象(基于ajax的一种封装),然后调用该对象的一些方法实现对后端数据接口的请求,在 node.js 中用于创建 http 请求,支持 Promise Api,可以使用 async/await 语法糖书写,便于拦截请求和响应,并对请求和响应的数据进行处理,自动转换 JSON 数据格式,同事用于客户端支持防御 XSRF。且目前主流浏览器都支持该库。
常见的安装方式有以下两种:
(1)使用 cdn 方式,代码中直接引入下面脚本即可,这种方式适用于小型项目,比如学习的小 demo 等。
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
(2)使用 npm 方式,直接在命令行中添加即可。
npm install axios
2.axios 常见用法?
axios中常用的请求配置如下,只有指定的url是必须项,其他存在默认配置项,method不特殊指定,默认方法为 get 。
{ url: '/user',
// `url` 是用于请求的服务器 URL method: 'get',
// default `method` 是创建请求时使用的方法 baseURL: 'https://some-domain.com/api/',
// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL headers: {'X-Requested-With': 'XMLHttpRequest'},
// `headers` 是即将被发送的自定义请求头 params: { ID: 12345 },
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象,`params` 是即将与请求一起发送的 URL 参数 timeout: 1000,
// 如果请求话费了超过 `timeout` 的时间,请求将被中断,`timeout` 指定请求超时的毫秒数(0 表示无超时时间) withCredentials: false,
// default `withCredentials` 表示跨域请求时是否需要使用凭证 responseType: 'json',
// default `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream' responseEncoding: 'utf8', // default onUploadProgress: function (progressEvent) {
// `onUploadProgress` 允许为上传处理进度事件 // Do whatever you want with the native progress event }, onDownloadProgress: function (progressEvent) {
// `onDownloadProgress` 允许为下载处理进度事件 // 对原生进度事件的处理 }, }
(1)get 请求
axios.get('url',{params:{ //这里是请求参数 }}) .then(res=>{
//这里是响应后操作 }) .catch(err=>{
//异常捕获 })
(2)post 请求
axios.post('url',{ name:xxx//参数 },{ headers:xxxx,//请求头信息 }) .then(function(res){ //处理成功的函数 相当于success }) .catch(function(error){ //错误处理 相当于error })
(3)all、spread 并发请求
axios.all([ axios.get('url'), axios.get('url',{params:{type:'sell',page:1}}) ]) .then(axios.spread((res1,res2)=>{ //返回结果为一个数组 }))
all()方法入参为一个数组,数组元素是每一项请求,回调函数 .then() 的参数也是一个数组,里面的每一项元素表示前面请求的返回结果,使用了 axios.spread作为该回调函数的参数时,其res1,res2分别代表前面每一项请求的返回结果。
综上这些方法都只使用于小型项目中,或者学习小 demo 中,在工作开发中遇到处理的请求接口较多,
3.axios 在项目中的常见用法?
(1)小型项目中常见封装方法,灵活性较高。
首先创建 axios.js 文件
import originAxios from 'axios' export default function axios(option){ return new Promise((resolve,reject)=>{ //创建axios实例 const instance=originAxios.create({ baseURL:'/api', timeout:5000, headers:'' }); //传入对象进行网络请求 instance(option) .then(res=>{ resolve(res) }) .catch(err=>{ reject(err) }) }) }
然后在需要发送请求接口的地方引入
import {axios} from './axios.js' axios({method:"get",url:"url",params:{...}}) .then(res=>{ //请求数据后操作 }) .catch(err=.{ //错误处理 })
(2)针对不同请求类型进行二次封装。
/* *url:请求的url *params:请求的参数 *config:请求时的header信息 *method:请求方法 */ const request = function ({ url, params, config, method }) { // 如果是get请求 需要拼接参数 let str = ""; if (method === "get" && params) { Object.keys(params).forEach((item) => { str += `${item}=${params[item]}&`; }); } return new Promise((resolve, reject) => { axios[method]( str ? url + "?" + str.substring(0, str.length - 1) : url, params, Object.assign({}, config) ) .then( (response) => { resolve(response.data); }, (err) => { if (err.Cancel) { } else { reject(err); } } ) .catch((err) => { reject(err); }); }); };
具体使用同上。
(3)基于请求响应拦截进行封装,实际项目开发中常用。
axios 提供的拦截器,用于每次发送请求和得到响应后进行响应的处理。比如在请求拦截中可以在页面中添加 loading 动画,某些请求要求用户必须登录,判断用户是否有token,如果没有就跳转到登录页面等,也可以对请求参数进行序列化操作等 config.data = qs.stringfy(config.params) 等。同样,响应拦截也可以对响应的数据进行过滤,包括响应失败的拦截,可以根据响应状态码进行不同的操作等。具体方法如下:
首先在工具方法文件夹中创建 request.js 文件。这里搭配了token用于判断用户状态,element-ui 组件处理一些错误报错提示。该文件封装暴露了get、post、文件上传方法。
import axios from "axios"; import store from "../store"; import { Message, MessageBox } from "element-ui"; let baseURL = "http://127.0.0.1:3000/"; // 创建axios实例 const service = axios.create({ baseURL: baseURL, timeout: 5000, // 请求超时时间 headers: { "Content-Type": "application/json;charset=UTF-8" }, }); // axios.defaults.withCredentials = true; // 若跨域请求需要带 cookie 身份识别 axios.defaults.headers.post["Access-Control-Allow-Origin-Type"] = "*"; // 允许跨域 const err = (error) => { if (error.response) { let data = error.response.data; const token = store.getters.token; switch (error.response.status) { case 403: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; case 500: if (token && data.message == "Token失效,请重新登录") { MessageBox.confirm( "很抱歉,登录已过期,请重新登录", "确定登出", { confirmButtonText: "重新登录", cancelButtonText: "取消", type: "warning", } ).then(() => { store.dispatch("Logout").then(() => { window.location.reload(); // 为了重新实例化vue-router对象 避免bug }); }); } break; case 404: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; case 504: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; case 401: Message({ message: data.message, type: "error", duration: 5 * 1000, }); if (token) { store.dispatch("Logout").then(() => { setTimeout(() => { window.location.reload(); }, 1500); }); } break; default: Message({ message: data.message, type: "error", duration: 5 * 1000, }); break; } } return Promise.reject(error); }; // request拦截器 service.interceptors.request.use( (config) => { const token = store.getters.token; if (store.getters.token) { config.headers["X-Token"] = token;//这里要注意在判断用户状态时候,请求头添加x-token格式问题,大写分开。 } return config; }, (error) => { // Do something with request error console.log(error); // for debug Promise.reject(error); } ); // respone拦截器 service.interceptors.response.use((response) => { console.log("response.data", response.data); return response.data; }, err); /* * get请求 * url:请求地址 * params:参数 * */ export function get(url, params = {}) { return new Promise((resolve, reject) => { console.log("process.env.BASE_API", process.env.BASE_API); service({ url: url, method: "get", params: params, }) .then((response) => { resolve(response); }) .catch((error) => { reject(error); }); }); } /* * post请求 * url:请求地址 * params:参数 * */ export function post(url, params = {}) { return new Promise((resolve, reject) => { service({ url: url, method: "post", data: params, //这里注意下请求数据放在query params还是body中。 }) .then((response) => { resolve(response); }) .catch((error) => { reject(error); }); }); } /* * 文件上传 * url:请求地址 * params:参数 * */ export function fileUpload(url, params = {}) { return new Promise((resolve, reject) => { console.log("@@@@@@@@@@@params", params); service({ url: url, method: "post", data: params, headers: { "Content-Type": "multipart/form-data" }, }) .then((response) => { resolve(response); }) .catch((error) => { reject(error); }); }); } export default { get, post, fileUpload, };
然后创建api文件夹,如果接口过多可以对接口进行模块化管理,比如我这 api 下面创建 login.js 文件。
import { get, post,fileUpload } from "../utils/request"; // 登录 export const login = (params) => { return get("/user/login", { ...params }); }; // 查询用户信息 export const getUserInfo = (params) => { return get("/user/userInfo", { ...params }); }; // 上传音频文件 export const addRadioApi = (params, file) => { return fileUpload("/radio/addRadio", { params, file }); };
最后在你的vue文件中就可以使用了,login.vue中使用如下:
import { login } from "../../api/login"; login({ name: "123", password: "123456" }) .then((res) => { //登录请求后操作 }) .catch((error) => { //异常处理 });
总结
以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长踩坑之路会持续更新一些工作中常见的问题和技术点。