一、前言
转眼间,来目前这家公司工作已经近一年了,虽然在这一年中有过很多抱怨(主要是关于产品、设计),但也收获良多。疫情期间,天灾人祸,人要生存,同样的公司也要,于是理所应当的一系列猛如虎的操作……以前也在想,一个工作到底能给我们本身带来什么?当你离职了,你又能得到什么?最近又不断的想着这个问题。
来JZ快一年了,还记得去这个时候正辛辛苦苦的准备着找工作,那个时候的自己,刚从后端转前端,做过一两个前端项目,但都是用pro框架来写的,很少涉及到原生的东西,本来就没啥基础的自己,CSS不熟、JS不熟,React还只是照猫画虎,ant组件也马马虎虎,找工作时,就算进了三面,也是满脑子的不自信。
这一年的时间里,自己写CSS样式,而且还是UI朝令夕改的那种,那个时候想着,反正自己啥都不会,就当学习了。因为工作的原因,用了大量的bizchart图表,也用到了echart(之前还停留在听说的阶段),还因为需求原因,不得不去学习纯前端导出PDF的实现,当然最主要的是现在的自己在前端开发上最起码不再那么不自信,畏畏缩缩了。
在公司负责的项目上线了,我想我也该总结下,毕竟我自己都担心哪天自己都忘记了那些文件、那些方法是自己一遍又一遍找同事商量、一遍又一遍测试后的产物。
二、工作中思维的火花
2.1、关于接口环境-动态获取当前项目运行环境
最开始待的那家公司,到后来,前端正式员工,就剩下唯一的自己了,因为之前的项目要给客户演示,但演示之前要有小的改动,需要连接本地环境测试,给客户演示时连接的是客户的服务器地址,所以,每次都要修改连接的地址。有的时候忘记修改地址了,关键是公司的全部文件都是加密的,每次打包都要申请解密,整个流程超级麻烦。老大找到我,说让我研究下怎么样可以不用修改文件之间打包,就是动态的设置项目环境。当时的自己,对这些完全没有任何经验,向已经离职的同事抱怨,他们建议我看看webpack文档,说不定能有收获。
终于不负所望,通过修改package.json中的node命令可以实现,激动之余,把所有可能的环境都设置了一遍。代码如下:
"start": "cross-env UMI_UI=none umi dev",
"start:prod": "cross-env ENVIRONMENT=production umi dev",
"build": "cross-env ENVIRONMENT=production umi build",
找不到最初的代码了,只好把现在项目的代码拿出来了,唉!真的是,明明是付出过的,可还是说忘记就忘记了。废话说太多了,总结下实现思路,如下:
1、定义变量用来区分运行环境
在运行命令时,通过cross-env 定义一个变量并赋不同的值,本次代码定义了ENVIRONMENT;
2、取出变量并暴露出去
在配置文件config.ts中,通过process.env.变量名取出变量,并根据不同的变量设置不同的服务器地址
const { ENVIRONMENT } = process.env;
define: {
'process.env.HOST': ENVIRONMENT === 'production' ? HostConfig.PROD : HostConfig.DEV,
},
3、在需要使用到的地方(一般是接口请求地址)引入后使用
const { HOST } = process.env;
2.2统一接口校验-返回数据并根据不同的状态做出反应
最开始参与公司项目时,一个空的壳子,除了框架做好的基础,啥都没有。频繁的对请求后的接口做是否成功的处理,关键是,每个后端返回数据成功的字段不一样,字段值也不一样,有着后端开发封装强迫症的我,再做了几次判断后,忍无可忍,于是,写了一个方法,每次直接调用就行。刚开始前端就我一个,后来随着参与的人多了,前端大佬又重新定义了一个工具类,嗯!功能确实很全,包括检查数据是否正确返回,当后端返回为401时,页面跳转到登录页面
/**
* Description:统一的 response 状态码检查
*/
import { message } from 'antd';
const SUCCESS_CODE_LIST = ['200', 200, '0', 0]; // 定义成功的状态码
const LOGIN_CODE = '401'; // 需要登录
/**
* 检查状态码是否为成功
* @param responseObject response对象
*/
export default function checkStatusCode(responseObject: any): boolean {
if (responseObject) {
if (
SUCCESS_CODE_LIST.includes(responseObject.code) ||
SUCCESS_CODE_LIST.includes(responseObject.status)
) {
return true;
}
if (responseObject.code === LOGIN_CODE || responseObject.status === LOGIN_CODE) {
window.location.href = '/login';
return false;
}
}
// 统一的消息提示
if (responseObject && responseObject.message) {
message.error(responseObject.message, 3);
}
return false;
}
2.3 service请求封装(pro中的service层)
1 、GET、POST、导出Excel等常用请求封装
/**
* Description:提供通用请求方法
*/
import request from '@/utils/request';
import appendParams from '@/utils/URLUtils';
/**
* GET 请求
* @param url 请求的 url
* @param params 参数
*/
export async function GET(url: string, params?: {}, options?: {}): Promise<any> {
return request(appendParams(url, params as {}), {
...options,
});
}
/**
* POST 请求
* @param url 请求的 url
* @param params 参数
*/
export async function POST(url: string, params?: {}, options?: {}): Promise<any> {
return request(url, {
method: 'POST',
data: params,
...options,
});
}
/**
* PUT 请求
* @param url 请求的 url
* @param params 参数
*/
export async function PUT(url: string, params?: {}): Promise<any> {
return request(url, {
method: 'PUT',
data: params,
});
}
/**
* DELETE 请求
* @param url 请求的 url
* * @param params 参数
*/
export async function DELETE(url: string, params?: {}): Promise<any> {
return request(url, {
method: 'DELETE',
data: params,
});
}
/**
* POST 请求:仅仅用于导出Excel
* @param url 请求的 url
* * @param body 参数
*/
export async function EXPORTEXCEL(url: string, body?: {}): Promise<any> {
return request(url, {
method: 'POST',
data: body,
responseType: 'blob',
});
}
/**
* GET的导出EXCEl
* @param url
* @param body
* @constructor
*/
export async function EXPORTEXCELGET(url: string, params?: {}): Promise<any> {
return request(appendParams(url, params as {}), { responseType: 'blob' });
}
2、GET请求补充代码
/**
* 将参数拼接至 api
*/
export default function appendParams(api: string, params: object) {
let finalAPI = api;
if (params) {
Object.keys(params).forEach((key, index) =