一、概览
实现一个支持路由keepAlive,类似浏览器页签功能的react的模板项目。具体效果如下所示:
预览项目已经部署到了vercel。在线体验(速度较慢的话,可能访问阿里云在线)
项目源码地址
二、涉及技术
- react@18
- typescript
- vite@4.x
- react-router@6.x
- antd@5.x
- ahooks
- lodash-es
- react-beautiful-dnd
三、核心功能
- 类似umi的权限配置管理方案,可方便的对权限进行处理。
- 灵活的路由布局配置,可选择在左侧还是在头部。
- 类似浏览器页签的历史访问路径,支持拖拽,刷新,关闭等操作。
- 路由keepAlive的hack实现,能够缓存用户操作。
- 便捷的layout配置方案,类似antd-pro与umi的结合。
四、部分功能实现原理和使用方式
4.1 keepAlive
keepAlive是一个hack实现。在react想要实现keepAlive本质上就是要保证组件不被卸载。
组件是否被卸载的判断依据是,在update流程中,前后的两棵树中是否都具有此节点。如果有的节点在本次的render中没有返回,那么就会被打上删除的标识,相应的此节点也就会被卸载。
所以核心是,我们要保证组件不被卸载,查看核心代码
4.2 layout配置
layout的配置方式类似于umi + antd-pro的使用方式,对外暴露配置文件,在此文件中进行相应的选项配置即可。
// layout配置
export const layoutSettings: LayoutProProps = {
logo: IconLogo,
headerRight: <HeaderRight />,
headerHeight: 60,
siderWidth: 300,
defaultCollapsed: false,
maxLength: 10
// isTabs:false
// ...
}
4.3 项目初始化设置
对于希望在项目全局使用的信息或者组件加载出来前使用的数据,使用方式同umi一致:
// 初始化配置
export const getInitialState = async (): Promise<InitialStateType> => {
const values: InitialStateType = {
settings: layoutSettings,
userInfo: {},
accessInfo: []
}
// 获取用户登录信息
// const userRes = await reqGetUserInfo()
// if (!userRes.result) {
// // 跳转登录链接
// window.location.href = config.loginUrl
// return values
// } else if (userRes.message) {
// message.error(userRes.message)
// }
values.userInfo = {
nickName: 'thomas-void'
}
// values.settings.watermark = {
// text: values.userInfo.nickName
// }
return values
}
在需要使用的地方:
const { globalState } = useGlobal()
4.4 路由配置
针对路由,提供了多种配置方案:
interface RouteExtension {
/* 路由显示icon */
icon?: ReactNode
/* 在菜单中显示的名称,如果没有name则不在菜单中显示 */
name?: string
/* 权限相关 */
access?: string
/* 是否要开启keep-alive, 默认是false */
keepAlive?: boolean
/* layout布局相关,默认true */
layout?:
| boolean
| {
/* 渲染左边的sider组件 */
leftSiderRender?: boolean
/* 是否渲染到左边的菜单项中 */
leftItemRender?: boolean
/* 是否渲染头部header组件 */
headerRender?: boolean
/* 是否渲染到头部的菜单项目中 */
topItemRender?: boolean
}
/* 扩展的children */
children?: RouteConfig[]
}