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/#/,按照先前流程走一遍,没有问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/70713.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈Spring

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器&#xff08;框架&#xff09;。 一、什么是IOC&#xff1f; IoC Inversion of Control 翻译成中⽂是“控制反转”的意思&#xff0c;也就是说 Spring 是⼀个“控制反转”的容器。 1.1控制反转推导 这个控制反转怎…

远程访问服务器JupyterLab的配置方法【转载】

远程访问服务器JupyterLab的配置方法 环境及工具基本步骤生成密码生成并修改配置文件后台运行jupyter后台关闭 其实就是在服务器运行JupyterLab&#xff0c;然后在本地浏览器访问 环境及工具 服务器&#xff1a;Ubuntu 16.04 本机&#xff1a;Mac OS Catalina 10.15.3 Royal …

什么是 CSS

什么是 CSS CSS全称为Cascading Style Sheets&#xff0c;译为层叠样式表。样式定义如何显示HTML元素。样式通常存储在样式表中。 CSS 是能够真正做到网页表现与内容分离的一种样式设计语言。相对于传统 HTML 的表现而言&#xff0c;CSS 能够对网页中的对象的位置排版进行像素…

c语言逻辑思维

c语言逻辑思维 1.如何问问题? 有甲、乙两人&#xff0c;其中&#xff0c;甲只说假话&#xff0c;而不说真话;乙则是只说真话&#xff0c;不说假话。但是&#xff0c;他们两个人在回答别人的问题时&#xff0c;只通过点头与摇头来表示&#xff0c;不讲话。有一天&#xff0c;一…

Unity中Shader的时间_Time

文章目录 前言一、_Time.xyzw分别代表什么二、_Time怎么使用 前言 Unity中Shader的时间_Time 一、_Time.xyzw分别代表什么 _Time.y 代表当前时间 二、_Time怎么使用 在需要使用的地方直接 * _Time.y 或 x / z / w 测试代码&#xff1a; Shader "MyShader/P0_9_5&qu…

css 命名规则

一个有规则的命名 会提高代码的可读性 一、命名规则说明&#xff1a; 1&#xff09;、所有的命名最好都小写 2&#xff09;、属性的值一定要用双引号(“”)括起来 3&#xff09;、给图片加上alt标签 4&#xff09;、尽量使用英文命名原则 5&#xff09;、尽量不缩写&#xff0…

python容器模块Collections

Python附带一个模块&#xff0c;它包含许多容器数据类型&#xff0c;名字叫作collections defaultdict defaultdict与dict类型不同&#xff0c;你不需要检查key是否存在&#xff0c;所以我们能这样做&#xff1a; from collections import defaultdict colours ((Yasoob, Y…

angular 测试 api 说明

detectChanges(checkNoChanges?: boolean): void; 触发组件的变更检测周期。它重新评估组件的模板并相应地更新视图。checkNoChanges参数是可选的&#xff0c;可用于检查是否存在不应发生的任何更改。 checkNoChanges(): void; 执行变更检测运行&#xff0c;以确保组件没有意外…

Kali Linux渗透测试技术介绍【文末送书】

文章目录 写在前面一、什么是Kali Linux二、渗透测试基础概述和方法论三、好书推荐1. 书籍简介2. 读者对象3. 随书资源 写作末尾 写在前面 对于企业网络安全建设工作的质量保障&#xff0c;业界普遍遵循PDCA&#xff08;计划&#xff08;Plan&#xff09;、实施&#xff08;Do…

【网络爬虫笔记】爬虫Robots协议语法详解

Robots协议是指一个被称为Robots Exclusion Protocol的协议。该协议的主要功能是向网络蜘蛛、机器人等搜索引擎爬虫提供一个标准的访问控制机制&#xff0c;告诉它们哪些页面可以被抓取&#xff0c;哪些页面不可以被抓取。本文将进行爬虫Robots协议语法详解&#xff0c;同时提供…

管理学国际化与领导力视角

随着全球化的进程不断加速&#xff0c;管理学的国际化已经成为一个不可忽视的趋势。在这个多元化和全球化的时代&#xff0c;管理者需要具备跨文化的领导力&#xff0c;以适应不同国家和地区的商业环境&#xff0c;并有效地管理全球团队。本文将从管理学国际化和领导力的角度探…

Java # Java容器

Java容器的分类 List ArrayList 源码 public static vooid main(String[] args){ArrayList<String> list new ArrayList<>();list.add("hello");list.add(1, "hello");list.remove("hello"); } list.add("hello"); …

ts学习笔记

1.安装 npm install typescriptnext 2.vscode通过创建.vscode/settings.json来使用这个版本&#xff1b; { "typescript.tsdk":"./node_modules/typescript/lib" } 1. TypeScript 有两个“顶层类型”&#xff08;any和unknown&#xff09;&#xff0c;但…

Python代码雨

系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/article/details/1295031234漂浮爱心https://want…

InnoDB全文索引是如何实现的?

分析&回答 全文索引的底层实现为倒排索引。 为什么叫倒排索引&#xff08;反向索引&#xff09; 当表上存在全文索引时&#xff0c;就会隐式的建立一个名为FTS_DOC_ID的列&#xff0c;并在其上创建一个唯一索引&#xff0c;用于标识分词出现的记录行。你也可以显式的创建…

golang字符串转64位整数

在Go语言中&#xff0c;可以使用strconv包中的ParseInt函数将字符串转换为64位整数。以下是一个示例代码&#xff1a; package main import ( "fmt" "strconv" ) func main() { str : "12345" num, err : strconv.ParseInt(str, 10, 64…

LeetCode刷题笔记【26】:贪心算法专题-4(柠檬水找零、根据身高重建队列、用最少数量的箭引爆气球)

文章目录 前置知识860.柠檬水找零题目描述解题思路代码 406.根据身高重建队列题目描述解题思路代码 452. 用最少数量的箭引爆气球题目描述踩坑-进行模拟正确思路的贪心 总结 前置知识 参考前文 参考文章&#xff1a; LeetCode刷题笔记【23】&#xff1a;贪心算法专题-1&#x…

举例说明自然语言处理(NLP)技术

自然语言处理&#xff08;NLP&#xff09;技术是一种人工智能领域的技术&#xff0c;用于处理自然语言文本或语音信号。下面是一些自然语言处理技术的例子&#xff1a; 机器翻译&#xff1a;机器翻译是一种自然语言处理的技术&#xff0c;它可以将一种语言的文本翻译成另一种语…

docker指令

目录 1、docker命令 2、镜像和容器的关系 3、Dockfile中特殊语法 &#xff08;1&#xff09;CMD 和 ENTRYPOINT ① 普通案例 ② 特殊案例 a、dockfile中的命令 和 命令行中的命令有冲突 b、使用exec执行PID1的命令 ③【cmd、entrypoint】和 exec 的关系 &#xff08…

2023年05月 C/C++(八级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;道路 N个以 1 … N 标号的城市通过单向的道路相连:。每条道路包含两个参数&#xff1a;道路的长度和需要为该路付的通行费&#xff08;以金币的数目来表示&#xff09; Bob and Alice 过去住在城市 1.在…