React Router
前置路由拦截器:
项目学习
自定义布局
Ant Design的Layout布局
1.登录鉴权
1.1用户登录&信息验证
核心(手写mock模拟数据,在没有后端支持情况下)
登录页面请求逻辑:pages/login/index.js
bash
将响应的用户信息存储至localstorage、sessionstorage以及redux状态全局管理
function Login() {
const dispatch = useDispatch()
const setUserInfo = useCallback((info) => dispatch(setUserInfoAction(info)), [dispatch])
const { btnLoad, onFinish } = useLogin(setUserInfo);
}
function useLogin(setUserInfo) {
const [btnLoad, setBtnLoad] = useState(false);
const onFinish = (values) => {
setBtnLoad(true);
login(values)
.then((res) => {
console.log(res);
//用户信息存储至localstorage、sessionstorage
const { data, msg, status, token } = res;
setBtnLoad(false);
if (status === 1) return;
saveToken(token);
data.isLogin = true;
message.success(msg);
if (values.remember) {
saveUser(data);
}
//redux管理用户数据
setUserInfo(data);
})
.catch(() => {
setBtnLoad(false);
});
};
return { btnLoad, onFinish };
}
登录页面数据响应逻辑:
login->api/index.js->mock/index.js
api/index.js
import mock from "../mock/index";
const request = process.env.REACT_APP_MOCK === "1" ? mock : ajax;
const login = (data) => request.post("/login", data);
mock/index.js
let currentUser = {};
//不同类型用户
const userInfoList = [
{
user_id: 1,
username: "张同学",
account: "admin",
type_id: "超级管理员",
t_id: 1,
},
{
user_id: 2,
username: "王五",
account: "user",
type_id: "用户",
t_id: 2,
},
{
user_id: 4,
username: "李四",
account: "qq123456",
type_id: "游客",
t_id: 3,
},
{
user_id: 5,
username: "路过的老鼠",
account: "jake",
type_id: "低权游客",
t_id: 4,
},
{
user_id: 6,
username: "站长",
account: "superAdmin",
type_id: "超级管理员",
t_id: 1,
},
];
//userInfo
const userInfo = {
msg: "登录成功",
status: 0,
data: null,
};
//MockData
const MockData = {
"/getmenu": menu,
"/getpower": power,
"/login": userInfo,
};
//封装post
function post(url, data) {
return new Promise((res, rej) => {
setTimeout(() => {
switch (url) {
case "/login": {
//这简化,仅简单找用户账号
const info = userInfoList.find((u) => u.account === data.account);
if (info) {
//获取到用户信息,增加对象data属性
// MockData[url]:userInfo
MockData[url].data = info;
currentUser = info;
return res(MockData[url]);
}
message.error("未找到账号");
return;
}
default: {
res({ status: 1, msg: "暂无" });
break;
}
}
}, 100);
}).then((res) => {
if (res.status === 0) {
return res
} else {
message.error("接口暂未配置")
return Promise.reject("接口暂未配置")
}
});
}
const mock = { get, post };
export default mock;
数据结构:t_id为外键,当作权限控制标识符
{
"msg": "登录成功",
"status": 0,
"data": {
"user_id": 1,
"username": "张同学",
"account": "admin",
"type_id": "超级管理员",
"t_id": 1,
"isLogin": true
}
}
1.2 权限管理
不同用户,权限不同,左侧导航条不同
openedMenu: [], // 保存已经打开的菜单栏 用于侧边栏
openMenuKey: [], // 打开的菜单栏的key 用于顶部导航
selectMenuKey: [], // 选中菜单栏的key 用户侧边栏
menuList: [], // 用户菜单列表
currentPath: "", // 页面当前路径