背景
PC端管理系统,采用 ant design pro 方案,它是阿里的一个管理系统框架,技术栈是react。
相比vue,react一个先天不足是不支持 keep-alive,所以管理系统中的多页签功能难以实现。
调研
由于官方不支持,只能网上寻找各方大佬的开源插件。
目前选择的是 umi-plugin-keep-alive ,它是在 react-activation 基础上,针对阿里自己的 umi 进行的定制化封装,antd pro 核心也是 umi 技术,所以 umi-plugin-keep-alive 与 antd pro 可以完美搭配。
实现
插件找到了,接下来的难点是对框架的改造。
由于 ant design pro 封装的很厉害,操作灵活性并不高,以下是改造的一个思路。
1. 创建 BaseLayout 和 BaseTabs 两个组件
这一步是标签页与缓存的实现
// BaseTabs/index.tsx
import { Tabs } from 'antd';
import React from 'react';
import { useAliveController, useHistory, useLocation } from 'umi';
const { TabPane } = Tabs;
export default (): React.ReactElement => {
const { pathname } = useLocation();
const history = useHistory();
// 获取缓存列表
const { getCachingNodes, dropScope } = useAliveController();
const cachingNodes = getCachingNodes();
/**
* 点击tab,跳转页面
*/
const clickTab = (path: string) => {
history.push(path);
};
/**
* 关闭tab,销毁缓存
*/
const editTab = (path: any) => {
dropScope(path);
// 关闭当前页面,需跳转到其他页签
if (path === pathname) {
const index = cachingNodes.findIndex((item) => item.name === path);
if (index > 0) {
history.push(cachingNodes[index - 1].name as string);
} else {
history.push(cachingNodes[1].name as string);
}
}
};
return (
<Tabs
type="editable-card"
hideAdd
size="small"
activeKey={pathname}
onTabClick={clickTab}
onEdit={editTab}
>
{cachingNodes.map((node) => (
<TabPane tab={node.tabName} key={node.name} closable={cachingNodes.length > 1} />
))}
</Tabs>
);
};
// BaseLayout/index.tsx
import React from 'react';
import { KeepAlive } from 'umi';
import BaseTabs from '../BaseTabs';
export default (props: any): React.ReactElement => {
const { children, location } = props;
const { pathname } = location;
return (
<>
<BaseTabs />
<KeepAlive id={pathname} name={pathname} tabName={props.route.name}>
{children}
</KeepAlive>
</>
);
};
2. 将BaseLayout应用起来
这一步被卡了很久,不知道该怎么把功能和框架相关联,原来需要在路由配置里加 wrappers 属性,这个属性官方文档中没有体现,翻阅了很多网上案例才找到,代码如下。(这里是举个例子,实际可以遍历 routes统一加属性)
这样写好后,系统就可以自动根据路由,完成缓存的功能了。