前言
基于Vue3 + Vite + Element-plus 来构建一个常见的后台,做这个的原因还是在于理清技术细节,虽然这玩意到处都是,但对于前端经验不算多的我而言,还是有必要自己捣鼓一次的,此外本次使用JavaScript来开发,而不适用TypeScript,核心原因是,遇到一些问题时,请教周围的前端朋友发现他们都不太熟悉TypeScript,所以一些小问题因为其类型推断系统搞了很久,后面和解了,个人项目用JavaScript也没啥问题,下面我们开始吧。
本文会提供完整的代码,请放心食用。
使用yarn构建vue3项目:
yarn create vite DashboardFrameWork --template vue
yarn && yarn dev
然后安装相应的依赖:
yarn add element-plus --save
yarn add @element-plus/icons-vue --save
yarn add axios --save
yarn add sass --save
yarn add vue-router@next --save
yarn add vuex@next --save
我将依赖都安装到dependencies(--save)中。
就我个人理解,开发时使用的工具向的东西,比如vite、webpack、mockjs等,不需要在上线时依赖,那么就将其安装到devDependencies(--dev)中,反之则安装到dependencies中。
上述安装的依赖中,element-plus是UI框架,element-plus/icons-vue是UI框架的图标相关的支撑库,axios是HTTP请求库、sass是用于编写样式的CSS超集语言、vue-router用于实现单页面路由,vuex用于实现状态存储,很常见的Vue3全家桶。
封装axios
为了方便开发和代码模块化,多数项目在开始前会进行一些基本的封装并构建出项目的骨架。
首先,我们对axios库进行封装,如果单纯的使用axios库,其用法已经足够简单了,但结合后台业务情况,还是有必要对它进行二次封装,实现请求拦截、响应拦截。
创建src/utils/request.js,用于实现封装JavaScript的逻辑,先创建axios对象:
// 创建axios实例对象,添加全局配置
const service = axios.create({
baseURL: config.baseApi,
timeout: 8000,
});
接着实现请求拦截,实现每次请求前身份的校验:
// 请求拦截
service.interceptors.request.use((req) => {
const headers = req.headers;
const { token } = storage.getItem("userInfo") || {};
if (token) {
if (!headers.Authorization) headers.Authorization = "Bearer " + token;
}
return req;
});
上述代码中,从storage中获取userInfo的数据,我们可以通过chrome的开发者工具Application查看到storage中存储的数据:
![c9fbd42543cfa7d61b1d0c9a135a5d6e.png](https://i-blog.csdnimg.cn/blog_migrate/6c775264a0d3d7cc545c67d2f3ab9517.png)
我们在login时,将用户基础信息写入其中,每次请求前都会通过请求拦截做一次登录校验。
以类似的方式,我们可以实现响应拦截:
// 响应拦截
service.interceptors.response.use((res) => {
const { code, data, msg } = res.data;
if (code === 200) {
return data;
} else if (code === 500001) {
ElMessage.error(TOKEN_INVALID);
// 让错误信息展示一下,再跳转
setTimeout(() => {
router.push("/login");
}, 1500);
// 抛出异常
return Promise.reject(TOKEN_INVALID);
} else {
ElMessage.error(msg || NETWORK_ERROR);
return Promise.reject(msg || NETWORK_ERROR);
}
});
如果响应的code是200,则将数据正常返回,如果code不为200,则通过ELMessage给用户展示相关的错误信息,并通过路由方法跳转到login页面,一个小技巧是,失败时,不要立刻跳转到login页面,因为我们希望用户看到相关的报错信息,最后返回Promise.reject对象。
拦截相关的方法实现好后,再封装一下请求方法就好了:
function request(options) {
options.method = options.method || "get";
if (options.method.toLowerCase() === "get") {
options.params = options.data;
}
let isMock = config.mock;
// 兼容局部Mock的用法
if (typeof options.mock != "undefined") {
isMock = options.mock;
}
service.defaults.baseURL = isMock ? config.mockApi : config.baseApi;
return service(options);
}
上述代码中封装了request方法,这里的核心在于,请求的URL是Mock地址还是真实的后台地址。
通过Mock,前端可以在不需要后台提供出完整的API的情况下进行开发,很多前端开源项目会使用Mockjs来构建一个单独的serve来为前端项目提供数据,而这里我直接使用了在线的Mock服务(后文介绍)。
至此,我们可以通过如下方式来实现http请求:
request({
url: "/users/login",
method: "post",
data: {
username: "ayuliao",
pwd: "123"
}
}).then((res) => {
console.log(res);
});
request.js github位置:https://github.com/ayuLiao/DashboardFrameWork/blob/master/src/utils/request.js
配置文件
多数项目中,都会使用配置文件来管理相关的配置,我们也不例外。
创建src/config/config/index.js,代码如下:
/**
* 环境配置封装
*/
// import.meta.env.MODE 当前项目环境
const env = import.meta.env.MODE
const EnvConfig = {
development:{
baseApi:'/api',
mockApi:'https://www.fastmock.site/mock/xxx/api'
},
production:{
baseApi:'//xxx.com/api',
mockApi:'https://www.fastmock.site/mock/xxx/api'
}
}
export default {
env,
// 是否开启Mock
mock:true,
namespace:'manager',
...EnvConfig[env]
}
通过env.MODE来判断当前的环境,在Vue3中,默认情况下,开发服务器 (dev 命令) 运行在 development (开发) 模式,而 build 命令则运行在 production (生产) 模式(更多可看