Vue + Element UI 前端篇(三):工具模块封装
Vue + Element UI 实现权限管理系统 前端篇(三):工具模块封装
封装 axios 模块
封装背景
使用axios发起一个请求是比较简单的事情,但是axios没有进行封装复用,项目越来越大,会引起越来越多的代码冗余,让代码变得越来越难维护。所以我们在这里先对 axios 进行二次封装,使项目中各个组件能够复用请求,让代码变得更容易维护。
封装要点
- 统一 url 配置
- 统一 api 请求
- request (请求) 拦截器,例如:带上token等,设置请求头
- response (响应) 拦截器,例如:统一错误处理,页面重定向等
- 根据需要,结合 Vuex 做全局的 loading 动画,或者错误处理
- 将 axios 封装成 Vue 插件使用
文件结构
在 src 目录下,新建一个 http 文件夹,用来存放 http 交互 api 代码。
config.js:axios 默认配置,包含基础路径等信息。
axios.js:二次封装 axios 模块,包含拦截器等信息。
interface.js :请求接口汇总模块,聚合模块 API。
index.js:将 axios 封装成插件,按插件方式引入。
config.js
export default {method: 'get',// 基础url前缀baseURL: 'http://localhost:8080/',// 请求头信息headers: {'Content-Type': 'application/json;charset=UTF-8'},// 参数data: {},// 设置超时时间timeout: 10000,// 携带凭证withCredentials: true,// 返回数据类型responseType: 'json' }
axios.js
import axios from 'axios'; import config from './config'; import qs from 'qs'; import Cookies from "js-cookie"; import router from '@/router'// 使用vuex做全局loading时使用 // import store from '@/store'export default function $axios(options) {return new Promise((resolve, reject) => {const instance = axios.create({baseURL: config.baseURL,headers: {},transformResponse: [function (data) {}]})// request 拦截器instance.interceptors.request.use(config => {let token = Cookies.get('token')// 1. 请求开始的时候可以结合 vuex 开启全屏 loading 动画// console.log(store.state.loading)// console.log('准备发送请求...')// 2. 带上tokenif (token) {config.headers.accessToken = token} else {// 重定向到登录页面router.push('/login')}// 3. 根据请求方法,序列化传来的参数,根据后端需求是否序列化if (config.method === 'post') {if (config.data.__proto__ === FormData.prototype|| config.url.endsWith('path')|| config.url.endsWith('mark')|| config.url.endsWith('patchs')) {} else {config.data = qs.stringify(config.data)}}return config},error => {// 请求错误时console.log('request:', error)// 1. 判断请求超时if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1) {console.log('timeout请求超时')// return service.request(originalRequest);// 再重复请求一次}// 2. 需要重定向到错误页面const errorInfo = error.responseconsole.log(errorInfo)if (errorInfo) {error = errorInfo.data // 页面那边catch的时候就能拿到详细的错误信息,看最下边的Promise.rejectconst errorStatus = errorInfo.status; // 404 403 500 ...router.push({path: `/error/${errorStatus}`})}return Promise.reject(error) // 在调用的那边可以拿到(catch)你想返回的错误信息})// response 拦截器instance.interceptors.response.use(response => {let data;// IE9时response.data是undefined,因此需要使用response.request.responseText(Stringify后的字符串)if (response.data == undefined) {data = JSON.parse(response.request.responseText)} else {data = response.data}// 根据返回的code值来做不同的处理switch (data.rc) {case 1:console.log(data.desc)break;case 0:store.commit('changeState')// console.log('登录成功')default:}// 若不是正确的返回code,且已经登录,就抛出错误// const err = new Error(data.desc)// err.data = data// err.response = response// throw errreturn data},err => {if (err && err.response) {switch (err.response.status) {case 400:err.message = '请求错误'breakcase 401:err.message = '未授权,请登录'breakcase 403:err.message = '拒绝访问'breakcase 404:err.message = `请求地址出错: ${err.response.config.url}`breakcase 408:err.message = '请求超时'breakcase 500:err.message = '服务器内部错误'breakcase 501:err.message = '服务未实现'breakcase 502:err.message = '网关错误'breakcase 503:err.message = '服务不可用'breakcase 504:err.message = '网关超时'breakcase 505:err.message = 'HTTP版本不受支持'breakdefault:}}console.error(err)return Promise.reject(err) // 返回接口返回的错误信息})// 请求处理instance(options).then(res => {resolve(res)return false}).catch(error => {reject(error)})}) }
interface.js
import axios from './axios'/* * 将所有接口统一起来便于维护* 如果项目很大可以将 url 独立成文件,接口分成不同的模块*/// 单独导出 export const login = () => {return axios({url: '/login',method: 'get'}) }export const getUser = () => {return axios({url: '/user',method: 'get'}) }export const getMenu = data => {return axios({url: '/menu',method: 'post',data}) }// 默认全部导出 export default {login,getUser,getMenu }
index.js
// 导入所有接口 import apis from './interface'const install = Vue => {if (install.installed)return;install.installed = true;Object.defineProperties(Vue.prototype, {// 注意,此处挂载在 Vue 原型的 $api 对象上$api: {get() {return apis}}}) }export default install
安装 js-cookie
上面 axios.js 中,会用到 Cookie 获取 token,所以需要把相关依赖安装一下。
执行以下命令,安装依赖包。
yarn add js-cookie
代码实例
1.引入插件
在 main.js 中以 vue 插件的形式引入 axios,这样在其他地方就可通过 this.$api 调用相关的接口了。
2.编写接口
在 interface.js 中添加 login 接口。
3.调用接口
在登录界面 Login.vue 中,添加一个登录按钮,点击处理函数通过 axios 调用 login 接口返回数据。
成功返回之后,将 token 放入 Cookie 并跳转到主页。
<template><div class="page"><h2>Login Page</h2><el-button type="primary" @click="login()">登录</el-button></div> </template><script>import mock from '@/mock/mock.js';import Cookies from "js-cookie";import router from '@/router'export default {name: 'Login',methods: {login() {this.$api.login().then(function(res) {alert(res.data.token)Cookies.set('token', res.data.token) // 放置token到Cookie router.push('/') // 登录成功,跳转到主页}).catch(function(res) {alert(res);});}}} </script>
4.mock 接口
在 mock.js 中添加 login 接口进行拦截,返回一个 token。
启动测试
浏览器访问:http://localhost:8080/#/login,显示登录界面。
点击登录按钮,首先弹出框,显示返回的 token 信息。
点击确定关掉弹出框后,跳转到主页。点击用户、菜单按钮,接口调用正常。
封装 mock 模块
为了统一可以统一管理和集中控制数据模拟接口,我们对 mock 模块进行了封装,可以方便的定制模拟接口的统一开关和个体开关。
文件结构
在 mock 目录下新建一个 index.js ,创建 modules 目录并在里面创建三个模块 *.js 文件。
index.js:模拟接口模块聚合文件
login.js:登录相关的接口模拟
user.js:用户相关的接口模拟
menu.js:菜单相关的接口模拟
index.js
import Mock from 'mockjs' import * as login from './modules/login' import * as user from './modules/user' import * as menu from './modules/menu'// 1. 开启/关闭[业务模块]拦截, 通过调用fnCreate方法[isOpen参数]设置. // 2. 开启/关闭[业务模块中某个请求]拦截, 通过函数返回对象中的[isOpen属性]设置. fnCreate(login, true) fnCreate(user, true) fnCreate(menu, true)/*** 创建mock模拟数据* @param {*} mod 模块* @param {*} isOpen 是否开启?*/ function fnCreate (mod, isOpen = true) {if (isOpen) {for (var key in mod) {((res) => {if (res.isOpen !== false) {Mock.mock(new RegExp(res.url), res.type, (opts) => {opts['data'] = opts.body ? JSON.parse(opts.body) : nulldelete opts.bodyconsole.log('\n')console.log('%cmock拦截, 请求: ', 'color:blue', opts)console.log('%cmock拦截, 响应: ', 'color:blue', res.data)return res.data})}})(mod[key]() || {})}} }
login.js
// 登录接口 export function login () {return {// isOpen: false,url: 'http://localhost:8080/login',type: 'get',data: {'msg': 'success','code': 0,'data': {'token': '4344323121398'// 其他数据}}} }
user.js
// 获取用户信息 export function getUser () {return {// isOpen: false,url: 'http://localhost:8080/user',type: 'get',data: {'msg': 'success','code': 0,'data': {'id': '@increment', 'name': '@name', // 随机生成姓名'email': '@email', // 随机生成姓名'age|10-20': 12// 其他数据}}} }
menu.js
// 获取菜单信息 export function getMenu () {return {// isOpen: false,url: 'http://localhost:8080/menu',type: 'get',data: {'msg': 'success','code': 0,'data': {'id': '@increment', 'name': 'menu', // 随机生成姓名'order|10-20': 12// 其他数据}}} }
修改引入
Login.vue
Home.vue
启动测试
浏览器访问:http://localhost:8080/#/,按照先前流程走一遍,没有问题。
相关文章:

Vue + Element UI 前端篇(三):工具模块封装
Vue Element UI 实现权限管理系统 前端篇(三):工具模块封装 封装 axios 模块 封装背景 使用axios发起一个请求是比较简单的事情,但是axios没有进行封装复用,项目越来越大,会引起越来越多的代码冗余&am…...

【pytorch】数据加载dataset和dataloader的使用
1、dataset加载数据集 dataset_tranform torchvision.transforms.Compose([torchvision.transforms.ToTensor(),])train_set torchvision.datasets.CIFAR10(root"./train_dataset",trainTrue,transformdataset_tranform,downloadTrue) test_set torchvision.data…...

搭建单机版FastDFS分布式文件存储系统
一、准备工作 1、下载FastDFS安装包和依赖包 https://codeload.github.com/happyfish100/libfastcommon/tar.gz/V1.0.43 https://codeload.github.com/happyfish100/fastdfs/tar.gz/V6.06 https://codeload.github.com/happyfish100/fastdfs-nginx-module/tar.gz/V1.22 注&…...

【验证码逆向专栏】房某下登录滑块逆向分析
声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 本文章未…...
Python 3.11 版本是对线程安全做了什么更改吗
问题:这份代码在 3.11.3 中它居然输出 0 ,一度以为自己写错了,抱着不信邪的态度,又搞了个 Python 3.9.7 的环境试了下,果然还是符合自己预期,输出不为 0,想问下 3.11 版本中是做了什么修改吗&am…...

【Docker】镜像的创建、管理与发布
镜像的获取 镜像可以从以下方式获得: 从远程镜像仓库拉取,可以是公有仓库,也可以是私有仓库从Dockerfile构建从文件导入(离线)从容器提交 镜像的基本操作 跟镜像相关的命令如下: $ docker image --help…...

移动硬盘或U盘无法弹出的解决方法
以下内容源于网络资源的学习与整理,如有侵权请告知删除。 最近在红米本win11中总遇到“该设备正在使用中”而无法弹出硬盘的问题。 解法该问题的思路:先定位占用该设备的进程,然后结束该进程。 定位进程 既然设备被占用,那肯定…...

(leetcode1761一个图中连通三元组的最小度数,暴力+剪枝)-------------------Java实现
(leetcode1761一个图中连通三元组的最小度数,暴力剪枝)-------------------Java实现 题目表述 给你一个无向图,整数 n 表示图中节点的数目,edges 数组表示图中的边,其中 edges[i] [ui, vi] ,…...

【漏洞复现】金和OA C6任意文件读取漏洞
漏洞描述 金和OA协同办公管理系统C6软件共有20多个应用模块,160多个应用子模块,涉及的企业管理业务包括协同办公管理、人力资源管理、项目管理、客户关系管理、企业目标管理、费用管理等多个业务范围,从功能型的协同办公平台上升到管理型协同…...

2023年全国大学生数学建模B题
多波束测线问题 1.问题提出 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀 速直线传播,在不同界面上产生反射,利用这一原理,从测量船换能器垂直向海底发射声波信号,并记录从声波发射到信号接…...
【LeetCode】2651.计算列车到站时间
题目 给你一个正整数 arrivalTime 表示列车正点到站的时间(单位:小时),另给你一个正整数 delayedTime 表示列车延误的小时数。 返回列车实际到站的时间。 注意,该问题中的时间采用 24 小时制。 示例 1:…...

Redis——认识Redis
简单介绍 Redis诞生于2009年,全称是Remote Dictionary Server,远程词典服务器,是一个基于内存的键值型NoSQL数据库。 特征 键值(Key-value)型,value支持多种不同数据结构,功能丰富单线程&…...

通讯录怎么导入新手机?3个推荐小妙招
最近刚换了新手机,旧手机里的联系人太多了,不想在新手机上一个个重新添加。有没有什么快速简单的方法能够将通讯录导入新手机? 大家在更换新手机之后都是怎么导入通讯录的呢?换手机最重要的就是把数据进行完整转移,那么…...

Geoserver发布shp、tiff、瓦片等格式的GIS数据
这里写目录标题 1 发布shp矢量数据1.1 添加shp作为数据源1.2 发布shp图层1.3 预览服务1.4 配置样式 2 发布Postgres数据库2.2 发布数据 3 发布 tif 栅格数据3.1 添加 tif 数据源3.2 发布tif数据3.3 预览服务3.4 配置地图样式 关于中文标注乱码的问题 1 发布shp矢量数据 发布sh…...

读书笔记-《ON JAVA 中文版》-摘要24[第二十一章 数组]
文章目录 第二十一章 数组1. 数组特性2. 一等对象3. 返回数组4. 多维数组5. 泛型数组6. Arrays的fill方法7. Arrays的setAll方法8. 数组并行9. Arrays工具类10. 数组拷贝11. 数组比较12. 流和数组13. 数组排序14. binarySearch二分查找15. 本章小结 第二十一章 数组 1. 数组特…...

go语言基本操作---五
error接口的使用 Go语言引入了一个关于错误处理的标准模式,即error接口,它是Go语言内建的接口类型 type error interface {Error() string }package mainimport ("errors""fmt" )type Student struct {name stringid int }func …...

【sgLazyTree】自定义组件:动态懒加载el-tree树节点数据,实现增删改、懒加载及局部数据刷新。
特性 可以自定义主键、配置选项支持预定义节点图标:folder文件夹|normal普通样式多个提示文本可以自定义支持动态接口增删改节点可以自定义根节点Id可以设置最多允许添加的层级深度 sgLazyTree源码 <template><div :class"$options.name" v-lo…...
Rust个人学习笔记
感悟:感觉rust好像缝合怪,既有python的影子,又有java和cpp的影子,可能这就是新型编程语言趋势吧。而且他的各种规范很严格很规范,比java还更工程,各种规范不对都有warning。 命名规范:蛇形命名…...
Java根据身份证号码提取出省市区,JSON数据格式
package com.rdes.talents.utils;import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern;/*** Author: 更多实用源码 www.cx1314.cn* Date: 2023/9/7 …...

MySQL知识笔记——初级基础(实施工程师和DBA工作笔记)
老生长谈,MySQL具有开源、支持多语言、性能好、安全性高的特点,广受业界欢迎。 在数据爆炸式增长的年代,掌握一种数据库能够更好的提升自己的业务能力(实施工程师)。 此系列将会记录我学习和进阶SQL路上的知识…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...