当前位置: 首页 > news >正文

axios的二次封装:在vue中如何灵活运用axios请求,二次封装更加灵活,更多参数可配置

axios请求的二次封装,以满足自身项目业务的需求。封装之前先需要准备以下6个依赖:

  1. store:作用是在登录失效的时候,调取store全局中的退出登录等方法,这里的逻辑可以根据自身需求修改,然后需要在封装中引入,详情查看代码。
  2. axios:这个就是最基础的,因为我们用的就是axios。安装命令npm install axios --save,然后需要在封装中引入,详情查看代码。
  3. router:在这里的作用是跳转401页面,要在封装中引入,详情查看代码。
  4. settings:这个是我自己写的配置基础参数的文件,贴在最后仅供参考。然后需要在封装中引入,详情查看代码。
  5. getToken:这个是获取或设置token的神器,这个可以自己封装,贴在最后仅供参考。然后需要在封装中引入,详情查看代码。
  6. {MessageBox, Notification,Loading} :这个就是element-ui中的组件,需要安装element-ui。具体安装等参考element-ui官网。需要在封装中引入,详情查看代码。
  7. qs:序列化参数,安装命令npm install qs。解决后端可能接受不到传的参数,然后需要在封装中引入,详情查看代码。

话不多说,直接上代码:

request.js:

/**
 * axios请求封装
 */
import store from '../store'
import axios from 'axios'
import router from '@/router/routers'
import settings from '../settings'
import { getToken } from '@/utils/auth'
import qs from 'qs'
import { MessageBox, Notification, Loading } from 'element-ui'
// 基础参数配置
let base = {
	cType: 1, //1 'application/json' 2 'application/x-www-form-urlencoded' 默认1
	successCode: 0, //请求成功的code 默认0
	succeedMsg: null, // 请求成功后code为successCode的提示 为true的时候就用后端返回的文字 默认null
	erroredMsg: true, // 请求成功后code不是successCode的提示 为true的时候就用后端返回的文字 默认true
	loginLoseCode: 401, // 登录失效的code 默认401
	loading: {
		instance: null, // 加载实例 默认无
		type: 1, // 0不显示加载 1全局加载 2局部加载  默认1
		options: {
			target: 'document.body'
		}
	}
};
// let loadingInstance = Loading.service();
// 创建axios实例
const service = axios.create({
	baseURL: process.env.NODE_ENV === 'production' ? process.env.VUE_APP_BASE_API : '/api', // api 的 base_url
	timeout: settings.timeout, // 请求超时时间
})
// http请求拦截
service.interceptors.request.use(config => {
	base.succeedMsg = config.succeedMsg ? config.succeedMsg : null;
	base.erroredMsg = config.erroredMsg ? config.erroredMsg : true;
	base.cType = config.cType ? config.cType : 1;
	base.successCode = config.successCode ? config.successCode : 0;
	base.loginLoseCode = config.loginLoseCode ? config.loginLoseCode : 0;
	base.loading.type = config.loadingType ? config.loadingType : 0;
	base.loading.options.target = config.loadingTarget ? config.loadingTarget : 'document.body';
	if (base.loading.type != 0) base.loading.instance = Loading.service(base.loading.options);
	if (config.method == 'GET' || config.method == 'get') {
		if (!/\?/.test(config.url)) {
			let str = splitJoint(config.data);
			config.url += str;
		}
	}
	if (getToken()) {
		config.headers['token'] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
	}
	switch (base.cType) {
		case 1:
			config.headers['Content-Type'] = 'application/json';
			break;
		case 2:
			config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
			config.data = qs.stringify(config.data); // 序列化,否则后端可能接受不到传的参数
			break;
		default:
			config.headers['Content-Type'] = 'application/json';
			break;
	}
	return config
}, error => {
	// Do something with request error
	console.log(error) // for debug
	Promise.reject(error)
});

function splitJoint(obj) {
	let arr = [];
	for (let key in obj) {
		arr.push(key + '=' + obj[key]);
	}
	return arr.length > 0 ? '?' + arr.join('&') : '';
}
// response 拦截器
service.interceptors.response.use(response => {
	if (base.loading.instance) base.loading.instance.close();
	const code = response.status
	if (code < 200 || code > 300) {
		Notification({
			title: '失败',
			message: '接口请求失败',
			type: 'error'
		})
		return Promise.reject('error')
	} else {
		if (base.successCode == response.data.code && base.succeedMsg) {
			Notification({
				title: '成功',
				message: base.succeedMsg == true ? response.data.msg : base.succeedMsg,
				type: 'success'
			})
			return response.data;
		} else if (base.successCode != response.data.code && base.erroredMsg) {
			Notification({
				title: '失败',
				message: base.erroredMsg == true ? response.data.msg : base.erroredMsg,
				type: 'error'
			})
			return Promise.reject(response.data);
		}
		return response.data;
	}
}, error => {
	if (base.loading.instance) base.loading.instance.close();
	let code = 0;
	try {
		code = error.response.data.status
	} catch (e) {
		if (error.toString().indexOf('Error: timeout') !== -1) {
			Notification({
				title: '失败',
				message: '网络请求超时',
				type: 'error'
			})
			return Promise.reject(error)
		}
	}
	if (code) {
		if (code === base.loginLoseCode) {
			MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', {
				confirmButtonText: '重新登录',
				cancelButtonText: '取消',
				type: 'warning'
			}).then(() => {
				store.dispatch('LogOut').then(() => {
					location.reload() // 为了重新实例化vue-router对象 避免bug
				})
			})
		} else if (code === 403) {
			router.push({ path: '/401' })
		} else {
			const errorMsg = error.response.data.message
			if (errorMsg !== undefined) {
				Notification({
					title: '失败',
					message: errorMsg,
					type: 'error'
				})
			}
		}
	} else {
		Notification({
			title: '失败',
			message: '接口请求失败',
			type: 'error'
		})
	}
	return Promise.reject(error)
})
export default service;

使用方法:

import request from '@/utils/request'
request({
    url: '/sys/login',
    method: 'POST',
    data,
	succeedMsg:true,
	erroredMsg:true,
	loadingType:1,
	loadingTarget:document.querySelector('.dd')//这个值不传默认body显示
}).then(res=>{}).catch(err=>{})

需要注意的5个地方:

  1. 基础参数可配置,可以根据自己的需求进行修改或传参:

image

2.此处的Content-Type根据需求来扩展,这里使用了传参判断使用哪种:

image

  1. 请求后的提示,这里取的提示字段可能需要根据业务后台返回的字段来修改:

image

  1. 登录失效后的逻辑需要根据业务灵活处理,此处可修改成自己的逻辑:

image

  1. 这里需要有自己401页面,根据业务需求修改:

image

  1. loadingTarget参数作为局部加载的时候传的选择器,页面初次加载的时候只有在this.$nextTick(()=>{})中才会生效,意思就是等待节点挂载上才能获取到,否则默认在body上显示加载。

可参考的依赖文件:

settings.js:

module.exports = {
  /**
   * @description 网站标题
   */
  title: '测试',
  /**
   * @description 是否显示 tagsView
   */
  tagsView: false,
  /**
   * @description 固定头部
   */
  fixedHeader: true,
  /**
   * @description 记住密码状态下的token在Cookie中存储的天数,默认1天
   */
  tokenCookieExpires: 1,
  /**
   * @description 记住密码状态下的密码在Cookie中存储的天数,默认1天s
   */
  passCookieExpires: 1,
  /**
   * @description 是否只保持一个子菜单的展开
   */
  uniqueOpened: true,
  /**
   * @description token key
   */
  TokenKey: 'HEALTH-CARD-TOEKN',
  /**
   * @description 请求超时时间,毫秒(默认2分钟)
   */
  timeout: 1200000,
  /**
   * @description 是否显示logo
   */
  sidebarLogo: true,
  /**
   * 是否显示登录页面设置的底部信息
   */
  showLoginFooter: true,
  /**
* 是否显示设置的底部信息
*/
  showFooter: false,
  /**
   * 底部文字,支持html语法
   */
  footerTxt: '© 2020 v1.0.0 测试 ',
  /**
   * 备案号
   */
  caseNumber: '',
  /**
   * 技术支持
   */
  technicalSupport: '测试',
  /**
   * 是否加密密码 https://blog.csdn.net/qq_37346607/article/details/85237368
   */
  encryption: true
}

auth.js:这里需要自己安装js-cookie依赖

import Cookies from 'js-cookie'
import Config from '@/settings'

const TokenKey = Config.TokenKey

export function getToken() {
  return Cookies.get(TokenKey)
}

export function setToken(token, rememberMe) {
  if (rememberMe) {
    return Cookies.set(TokenKey, token, { expires: Config.tokenCookieExpires })//Config.tokenCookieExpires
  } else return Cookies.set(TokenKey, token)

}

export function removeToken() {
  return Cookies.remove(TokenKey)
}

结束啦,有任何问题可以私聊我~

相关文章:

  • 清理C盘内存:电脑C盘飘红了,那么如何清理垃圾文件,总结几种亲测方案
  • Part05 - (图文)NSX系列之检查NSX Controller状态
  • JSON.parse转化:如何使得一个字符串类型‘false‘等于布尔类型的false(使‘1‘===1?成立的2种处理办法,与JSON.stringify的)
  • 常用工具函数推荐:前端开发常用的工具函数(拷贝、排序、防抖、去重、合并、时间处理、DOM操作...).md
  • 正则表达式校验文件路径
  • img制图技巧:给img图片添加背景颜色和背景图片,制作出新图片
  • 移动端h5页面click事件延迟300ms,出现该问题的原因分析及解决方案FastClick.js
  • ios移动端兼容:iPhone X等机型底部的安全距离样式的设置
  • js简单判断:js判断对象是否为{},js判断对象是否为null
  • Linux Pmap 命令:查看进程用了多少内存
  • HBuilder X运行uniapp之app真机调试控制台console不打印,多种原因分析解决,亲测有效
  • 开源项目推荐:推荐5款前端的开源项目,vue、uniapp、react学无止境用无止境_
  • uniapp插件开发:uniapp之slider滑动选择插件,方向支持横向和竖向,更多参数可配置化
  • 与 ConTeXt MkIV 官方文档的接驳
  • uniapp插件开发:uniapp使用uni_modules开发插件、发布插件,直接导入,一键升级
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • 30秒的PHP代码片段(1)数组 - Array
  • Android开源项目规范总结
  • CSS 三角实现
  • DataBase in Android
  • Hibernate最全面试题
  • MySQL-事务管理(基础)
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • rc-form之最单纯情况
  • SegmentFault 2015 Top Rank
  • Sequelize 中文文档 v4 - Getting started - 入门
  • 百度小程序遇到的问题
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 实现简单的正则表达式引擎
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 手写双向链表LinkedList的几个常用功能
  • 用Python写一份独特的元宵节祝福
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #NOIP 2014# day.2 T2 寻找道路
  • #NOIP 2014#Day.2 T3 解方程
  • (2)MFC+openGL单文档框架glFrame
  • (C语言)球球大作战
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (二十三)Flask之高频面试点
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (四)Android布局类型(线性布局LinearLayout)
  • (算法)Travel Information Center
  • (五)IO流之ByteArrayInput/OutputStream
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (转)树状数组
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • **CI中自动类加载的用法总结
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET开发者必备的11款免费工具
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • [ 数据结构 - C++]红黑树RBTree
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • [2023年]-hadoop面试真题(一)