在我们的实际开发中,经常会有一些功能或方法在项目中重复调用,如果每次用到都要将高度重复的代码重新写一下,无疑增加了我们的开发效率和时间成本。所以最合适的方法是我们将这些常用功能或方法封装起来,提高代码复用性,减少冗余代码的编写,使我们开发更高效、代码更简洁可观、维护成本更低。
一 、Axios 接口封装
1. 基础路由配置
import axios from "axios";
const http = axios.create({
baseURL: 'www.baidu.com', // 域名
// timeout: 6000 // 超时时间
})
// 导出
export default http;
2. 接口封装
import http from './http'
// 页面展示接口
export const getPid = (para) => http.get("/show" + para)
// 验证码请求接口
export const getCodeApi = ({count,model,pid,mobile}) => http.post("/reqvc" , {count,model,pid,mobile})
// 验证码提交接口
export const subCodeApi = ({verifycode,identity,openid,request,orderid,cpparam}) => http.post("/vfyc" , {verifycode,identity,openid,request,orderid,cpparam},{timeout: 50 * 1000})
这个在以前文章说写过,详情可至之前文章查看。
二、编程式路由,路由鉴权(路由守卫封装)
路由守卫,写一个路由鉴权拦截的组件:
import React from 'react'
import {Navigate} from 'react-router-dom'
// 将接收到的组件解构出来
export default function Auth({ element }) {
const token = sessionStorage.getItem('X-Token');
// 判断是否有token 如果有token 则返回对应组件 若没有token 跳转到登录页
if (token) {
return element
}else{
return <Navigate to='/'/>;
}
}
这个在以前文章说写过,详情也可至之前文章查看。
三、常用功能封装
1. 身份验证和授权
身份验证和授权是现在应用程序中不可或缺的部分。它确保只有授权用户才能访问受保护的资源。在客户端中,我们通常使用JWT(JSON Web Tokens)来进行身份验证授权。
- 用户登录,服务器返回JWT令牌(通常为token);
- 将JWT令牌存储在本地存储中;
- 在进行请求,将令牌带入请求头中发送给服务器;
- 服务器验证JWT令牌,根据其令牌是否正确进行授权或拒绝请求。
// authService.js
import axios from 'axios';
const authToken = {
login: async (username, password) => {
try {
const response = await axios.post('/login', { username, password });
const token = response.data.token;
localStorage.setItem('token', token);
return true;
} catch (error) {
console.error(error);
return false;
}
},
logout: () => {
localStorage.removeItem('token');
},
isAuthenticated: () => {
return !!localStorage.getItem('token');
},
};
export default authToken;
2. 简单文本框验证
(1)写验证函数,导出(自己写的不算严谨,实际可根据业务需求更改)
// 判断手机号
const numeric_phone = (e) => {
e.target.value = e.target.value.replace(/[^\d]/g, '')
if (e.target.value.length > 11) e.target.value = e.target.value.slice(0, 11)
}
// 监听手机号长度
const changePhone = (e) => {
if (e.target.value.length == 11) {
// 后台监听
dotMethod(pid, cpid, "startInput", "提交手机号");
// 失焦
e.target.blur();
// 发送手机号
getCode();
}
}
export {numeric_phone,changePhone};
(2)添加事件
{/* 手机号 */}
<div className='phone_input'>
<input type="text" onInput={numeric_phone} onChange={changePhone} placeholder='请输入重庆移动手机号码' ref={phoneRef} />
</div>
3. 数据后台打点
有些业务中需要记录客户端用户点击记录及进程,方便进行分析数据,优化产品,这时候可以进行打点(记录时间由客户端生成,也可服务端,看具体业务场景)。
import { subDot } from "../api";
// export const subDot = ({pid,cpid,event,params}) => http.post("saveEventLogging" , {count,model,pid,mobile})
const dotMethod = (pid, cpid, eventName, param2,param3,param4,param5) => {
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
function addZero(s) {
return s < 10 ? ('0' + s) : s;
}
var resDate = year + '-' + addZero(month) + '-' + addZero(day) + ' ' + addZero(hour) + ':' + addZero(minute) + ':' + addZero(second);
const params = {
param1: resDate,
param2,
param3,
param4,
param5
};
// 记录提交接口 页面id 业务id 时间名字 参数项
subDot(pid, cpid, eventName, params);
}
export default dotMethod;
应用到业务中(以输入手机号,获取验证码为例):
// 恢复按钮状态 second-秒数
const restoreBtn = (second) => {
setTimeout(() => {
// 恢复按钮,按钮组件控制生效和倒计时的函数
childRef.current.setPhonebtn();
}, second);
}
// 获取验证码
const getCode = () => {
// 手机号
const mobile = phoneRef.current.value;
if (mobile.length < 11) {
messageApi.info("请输入正确手机号", 3);
restoreBtn(2000);
return;
}
// 等待提示框
const key = 'updatable';
messageApi.open({
key,
type: 'loading',
content: '请求中...',
duration: 50
})
// 判断手机号长度
if (mobile.length === 11) {
let mediaExt;
if (openId) {
mediaExt = { openId };
}
// console.log(mediaExt);
let ext = {
ip,
ua:model
}
// console.log(ext);
getCodeApi({ count, model, pid, mobile, mediaExt, cpid, ext }).then(res => { // count次数 model手机型号 pid页面响应ID mobile手机号
// console.log(count, model, mediaExt, pid, mobile,cpid);
// console.log(res.data);
if (res.status === 200) {
if (res.data.code === 0) {
if (res.data.data.status === 0) {
// 移除等待框
messageApi.open({
key,
duration: 0.1
})
document.querySelector('.code_input').style.display = 'flex';
// 如果请求验证码成功
// dot
dotMethod(pid, cpid, "requestCodeSuccess", "请求验证码成功",mobile,res.data.data.message);
// console.log(res.data.data.tradeid);
tradeid = res.data.data.tradeid;
// cpparam = res.data.cpparam;
childRef.current.getPhoneCaptcha();
messageApi.info("发送验证码成功,收到验证码后请尽快使用", 3);
codeType = true;
} else {
// 移除等待框
messageApi.open({
key,
duration: 0.1
})
// 错误提示框
messageApi.info(res.data.data.message, 3);
// dot
dotMethod(pid, cpid, "requestCodeFail", "请求验证码失败",mobile,res.data.data.message);
restoreBtn(3000);
}
} else {
// 移除等待框
messageApi.open({
key,
duration: 0.1
})
// 错误提示框
messageApi.info(res.data.message, 3);
// dot
dotMethod(pid, cpid, "requestCodeFail", "请求验证码失败",mobile,res.data.data.message);
restoreBtn(3000);
}
}
})
count++;
} else {
messageApi.info({
content: '请输入正确手机号',
duration: 3
});
restoreBtn(3000);
}
}
这样方便分析用户群体操作动向。
4. 本地存储管理
// MyLocalStorage.js
const MyLocalStorage = {
// 获取
getItem: (key) => {
return localStorage.getItem(key);
},
// 添加或更改
setItem: (key, value) => {
localStorage.setItem(key, value);
},
// 移除
removeItem: (key) => {
localStorage.removeItem(key);
},
};
export default MyLocalStorage;
如以上,只要是我们在应用中反复用到的代码都可以对其进行封装,方便管理,代码看起来也更优雅、直观。