Vue 项目中 Axios 封装 api 和调用请求的方法
Vue 项目的前期配置
安装并导入
在 main.js 中导入 axios
1
| import axios from "axios";
|
配置 config 文件中的代理地址
在 config 目录下修改 index.js 文件,这是主要书写配置多个后台接口。
vue-cli2 配置代码示例 —— config/index.js
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
| 'use strict' // Template version: 1.3.1 // see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = { dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', // 后端请求地址代理 // 配置后api再之后的页面调用时就直接指代 target 对应的路径 proxyTable: { // 可以配置多个代理,格式如下: '/api': { // 匹配所有以 '/api'开头的请求路径 target: 'http://localhost:4000', // 代理目标的基础路径 changeOrigin: true, // 支持跨域 pathRewrite: { // 重写路径: 去掉路径中开头的'/api' '^/api': '' } } }, }, }
|
vue-cli3 配置代码示例 —— config/index.js
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
| devServer: { overlay: { // 让浏览器 overlay 同时显示警告和错误 warnings: true, errors: true }, host: "localhost", port: 8080, // 端口号 https: false, // https:{type:Boolean} open: false, //配置后自动启动浏览器 hotOnly: true, // 热更新 // proxy: 'http://localhost:8080' // 配置跨域处理,只有一个代理 proxy: { //配置多个代理 "/testIp": { target: "http://197.0.0.1:8088", changeOrigin: true, ws: true,//websocket支持 secure: false, pathRewrite: { "^/testIp": "/" } }, "/elseIp": { target: "http://197.0.0.2:8088", changeOrigin: true, //ws: true,//websocket支持 secure: false, pathRewrite: { "^/elseIp": "/" } }, } }
|
封装 axios 实例 — src/utils/rquest.js
在项目 src 目录下新建 utils 文件夹,然后在其中新建 request.js 文件,这个文件是主要书写 axios 的封装过程。
1、导入 axios
1
| import axios from 'axios'
|
2、环境的切换设置
1 2 3 4 5 6 7 8 9 10 11 12
| //在开发环境中的测试 development if(process.env.NODE_ENV == 'development') { axios.defaults.baseURL = 'http://xxxxxx' } //在生产环境中的测试 production if(process.env.NODE_ENV == 'production') { axios.defaults.baseURL = 'http://xxxxxx' } //还有一种环境 debug if(process.env.NODE_ENV == 'debug') { axios.defaults.baseURL = 'http://xxxxxx' }
|
3、设置默认参数
1 2 3 4 5 6
| // 设置默认请求头 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' // 超时重新请求最大次数 axios.defaults.retry = 4; // 请求间隔 axios.defaults.retryDelay = 1000;
|
4、创建 axios 实例
封装公共接口的 baseUrl 时候,用了 webpack 中的全局变量 process.env.BASE_API,而不是直接写死 ip,也是为了适应多个后台或者开发的时候的 api 地址和发布的时候的 api 地址不一样这种情况。
1 2 3 4 5 6
| const service = axios.create({ // 公共接口 baseURL: process.env.BASE_API, // 超时时间 单位是ms,这里设置了5s的超时时间 timeout: 5 * 1000 })
|
5、设置请求拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| service.interceptors.request.use(config => { //发请求前做的一些处理,数据转化,配置请求头,设置token,设置loading等,根据需求去添加 config.data = JSON.stringify(config.data); //数据转化,也可以使用qs转换 config.headers = { 'Content-Type':'application/x-www-form-urlencoded' //配置请求头 } //注意使用token的时候需要引入cookie方法或者用本地localStorage等方法,推荐js-cookie const token = getCookie('名称'); //这里取token之前,你肯定需要先拿到token,存一下 if(token){ config.params = {'token':token} //如果要求携带在参数中 config.headers.token= token; //如果要求携带在请求头中 } return config }, error => { Promise.reject(error) })
|
为防止发起请求时,当前正在进行的相同请求,可以在请求拦截器中加入 hash 判断,将相同请求 url 拦截
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let cancel ,promiseArr = {} axios.interceptors.request.use(config => { //发起请求时,取消掉当前正在进行的相同请求 if (promiseArr[config.url]) { promiseArr[config.url]('操作取消') promiseArr[config.url] = cancel } else { promiseArr[config.url] = cancel } ...其他处理... return config }, error => { return Promise.reject(error) })
|
6、设置响应拦截器
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 55 56 57 58 59 60 61 62 63 64 65 66
| service.interceptors.response.use(response => { // 对响应数据做点什么 //接收到响应数据并成功后的一些共有的处理,关闭loading等 return response }, error => { /***** 接收到异常响应的处理开始 *****/ // 对响应错误做点什么 if (error && error.response) { // 1.公共错误处理 // 2.根据响应码具体处理 switch (error.response.status) { case 400: error.message = '错误请求' break; case 401: error.message = '未授权,请重新登录' break; case 403: error.message = '拒绝访问' break; case 404: error.message = '请求错误,未找到该资源' window.location.href = "/NotFound" break; case 405: error.message = '请求方法未允许' break; case 408: error.message = '请求超时' break; case 500: error.message = '服务器端出错' break; case 501: error.message = '网络未实现' break; case 502: error.message = '网络错误' break; case 503: error.message = '服务不可用' break; case 504: error.message = '网络超时' break; case 505: error.message = 'http版本不支持该请求' break; default: error.message = `连接错误${error.response.status}` } } else { // 超时处理 if (JSON.stringify(error).includes('timeout')) { Message.error('服务器响应超时,请刷新当前页') } error.message = '连接服务器失败' }
Message.error(error.message) /***** 处理结束 *****/ //如果不需要错误处理,以上的处理过程都可省略 return Promise.resolve(error.response) }) //4.导入文件 export default service
|
封装请求 — src/utils/http.js
在项目 src 目录下的 utils 文件夹中新建 http.js 文件,这个文件是主要书写几种请求的封装过程。
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
| // 导入封装好的axios实例 import request from './request'
const http ={ /** * methods: 请求 * @param url 请求地址 * @param params 请求参数 */ get(url,params){ const config = { method: 'get', url:url } if(params) config.params = params return request(config) }, post(url,params){ const config = { method: 'post', url:url } if(params) config.data = params return request(config) }, put(url,params){ const config = { method: 'put', url:url } if(params) config.params = params return request(config) }, delete(url,params){ const config = { method: 'delete', url:url } if(params) config.params = params return request(config) } } //导出 export default http
|
封装 API — src/api/api.js
在项目 src 目录下新建 api 文件夹,然后在其中新建 api.js 文件,这个文件是主要书写 API 的封装过程。
写法一:分类导出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import http from '../utils/http' // /** * @parms resquest 请求地址 例如:http://197.82.15.15:8088/request/... * @param '/testIp'代表vue-cil中config,index.js中配置的代理 */ let resquest = "/testIp/request/"
// get请求 export function getListAPI(params){ return http.get(`${resquest}/getList.json`,params) } // post请求 export function postFormAPI(params){ return http.post(`${resquest}/postForm.json`,params) } // put 请求 export function putSomeAPI(params){ return http.put(`${resquest}/putSome.json`,params) } // delete 请求 export function deleteListAPI(params){ return http.delete(`${resquest}/deleteList.json`,params) }
|
写法二:全部导出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import http from '../utils/http' // /** * @parms resquest 请求地址 例如:http://197.82.15.15:8088/request/... * @param '/testIp'代表vue-cil中config,index.js中配置的代理 */ let resquest = "/testIp/request/"
// get请求 export default{ getListAPI(params){ return http.get(`${resquest}/getList.json`,params) }, postFormAPI(params){ return http.post(`${resquest}/postForm.json`,params) } }
|
注意:一个项目中如果后台请求不是同一个 ip,而是多个 ip 的时候,可以在 api 文件夹下建立多个 js,用来调用请求。
如何调用
方法一:用到哪个 api 就调用哪个接口 —— 适用于上文接口分类导出
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
| import {getListAPI,postFormAPI, putSomeAPI, deleteListAPI} from '../utils/api'
methods: { //promise调用,链式调用, getList()括号内只接受参数; // get不传参 getList() { getListAPI().then(res => console.log(res)).catch(err => console.log(err)) },
//post传参 postForm(formData) { let data = formData postFormAPI(data).then(res => console.log(res)).catch(err => console.log(err)) },
//async await同步调用 async postForm(formData) { const postRes = await postFormAPI(formData) const putRes = await putSomeAPI({data: 'putTest'}) const deleteRes = await deleteListAPI(formData.name) // 数据处理 console.log(postRes); console.log(putRes); console.log(deleteRes); }, }
|
方法二 :把 api 全部导入,然后用哪个调用哪个 api—— 适用于全部导出
1 2 3 4 5 6 7 8
| import api from '@/api/api' methods: { getList() { api.getListAPI(data).then(res => { //数据处理 }).catch(err => console.log(err)) } }
|