思路:通過(guò)react-activation實(shí)現(xiàn)頁(yè)面緩存,通過(guò)umi-plugin-keep-alive將react-activation注入umi框架,封裝頁(yè)簽組件最后通過(guò)路由的wrappers屬性引入頁(yè)面。
瀏覽本博客之前先看一下我的博客實(shí)現(xiàn)的功能是否滿足需求,實(shí)現(xiàn)功能:
- 頁(yè)面緩存
- 關(guān)閉當(dāng)前頁(yè)
- 阻止事件傳播
- 鼠標(biāo)右鍵>關(guān)閉當(dāng)前
- 鼠標(biāo)右鍵>關(guān)閉其他
- 鼠標(biāo)右鍵>關(guān)閉左側(cè)
- 鼠標(biāo)右鍵>關(guān)閉右側(cè)
- 鼠標(biāo)右鍵>全部關(guān)閉(默認(rèn)跳轉(zhuǎn)到首頁(yè))
- 鼠標(biāo)右鍵>重新加載(刷新緩存頁(yè)面)
1.下載依賴
pnpm install?react-activation@0.12.4
pnpm install?umi-plugin-keep-alive@0.0.1-beta.35文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-804685.html
2.修改.umirc.ts文件配置
import { defineConfig } from '@umijs/max';
export default defineConfig({
plugins: ['umi-plugin-keep-alive'],
...
});
3.封裝組件?
src目錄下創(chuàng)建layouts文件夾,創(chuàng)建BaseLayout.tsx文件和BaseTabs.tsx、index.less文件文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-804685.html
// BaseLayout.tsx
import { KeepAlive, Outlet, useRouteProps } from '@umijs/max';
import React from 'react';
import BaseTabs from './BaseTabs';
export default (): React.ReactElement => {
const { originPath, name } = useRouteProps();
return (
<>
<BaseTabs />
<KeepAlive id={originPath} name={originPath} tabName={name}>
<Outlet />
</KeepAlive>
</>
);
};
// BaseTabs/index.tsx
import { history, useAliveController, useLocation } from '@umijs/max';
import { Dropdown, Tabs } from 'antd';
import React, { useState } from 'react';
import './index.less';
export default (): React.ReactElement => {
const { pathname } = useLocation();
// 獲取緩存列表
const { getCachingNodes, dropScope, clear, refreshScope } =
useAliveController();
const cachingNodes = getCachingNodes();
const [open, setOpen] = useState<{ path: string; open: boolean }>({
path: '',
open: false,
});
// 阻止右鍵事件冒泡
const onRightClick = (
e: React.MouseEvent<HTMLDivElement, MouseEvent>,
name: string,
) => open.open && open.path === name && e.stopPropagation();
// 點(diǎn)擊tab,跳轉(zhuǎn)頁(yè)面
const clickTab = (path: string) => {
history.push(path);
};
// 關(guān)閉tab,銷(xiāo)毀緩存
const editTab = (path: any) => {
dropScope(path);
// 關(guān)閉當(dāng)前頁(yè)面,需跳轉(zhuǎn)到其他頁(yè)簽
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);
}
}
};
// 關(guān)閉當(dāng)前頁(yè)
const onCurrent = (e: any) => {
let targetKey = JSON.parse(e?.key).name;
dropScope(targetKey);
// 關(guān)閉當(dāng)前頁(yè)面,需跳轉(zhuǎn)到其他頁(yè)簽
if (targetKey === pathname) {
const index = cachingNodes.findIndex((item) => item.name === targetKey);
if (index > 0) {
history.push(cachingNodes[index - 1].name as string);
} else {
history.push(cachingNodes[1].name as string);
}
}
};
// 關(guān)閉其他
const onOther = (e: any) => {
let targetKey = JSON.parse(e?.key).name;
history.push(targetKey);
clear();
};
//關(guān)閉左側(cè)
const onLeft = (e: any) => {
let targetKey = JSON.parse(e?.key).name;
const lastIndex = cachingNodes.findIndex((item) => item.name === pathname);
const currIndex = cachingNodes.findIndex((item) => item.name === targetKey);
if (currIndex > lastIndex) history.push(targetKey);
cachingNodes.forEach((item, index) => {
if (index < currIndex) {
dropScope(item?.name || '');
}
});
};
// 關(guān)閉右側(cè)
const onRight = (e: any) => {
let targetKey = JSON.parse(e?.key).name;
const lastIndex = cachingNodes.findIndex((item) => item.name === pathname);
const currIndex = cachingNodes.findIndex((item) => item.name === targetKey);
if (currIndex < lastIndex) history.push(targetKey);
cachingNodes.forEach((item, index) => {
if (index > currIndex) {
dropScope(item?.name || '');
}
});
};
// 關(guān)閉全部
const onAll = () => {
history.push('/home');
clear();
};
// 重新加載
const onRefresh = (e: any) => {
let targetKey = JSON.parse(e?.key).name;
refreshScope(targetKey);
};
const labelDropdown = (name: string, label: string) => {
const lastIndex = cachingNodes.findIndex((item) => item.name === name);
return (
<div onClick={(e) => onRightClick(e, name)}>
<Dropdown
trigger={['contextMenu']}
onOpenChange={(e) => setOpen({ path: name, open: e })}
menu={{
items: [
{
label: '關(guān)閉當(dāng)前',
key: JSON.stringify({ name, key: 'current' }),
disabled: cachingNodes.length <= 1,
onClick: onCurrent,
},
{
label: '關(guān)閉其他',
key: JSON.stringify({ name, key: 'other' }),
disabled: cachingNodes.length <= 1,
onClick: onOther,
},
{
label: '關(guān)閉左側(cè)',
key: JSON.stringify({ name, key: 'left' }),
disabled: lastIndex === 0,
onClick: onLeft,
},
{
label: '關(guān)閉右側(cè)',
key: JSON.stringify({ name, key: 'right' }),
disabled: lastIndex === cachingNodes.length - 1,
onClick: onRight,
},
{
label: '全部關(guān)閉',
key: JSON.stringify({ name, key: 'all' }),
onClick: onAll,
disabled: cachingNodes.length <= 1,
},
{
label: '重新加載',
key: JSON.stringify({ name, key: 'refresh' }),
onClick: onRefresh,
},
],
}}
>
<div className={cachingNodes.length > 1 ? 'dropdown-label' : ''}>
{label}
</div>
</Dropdown>
</div>
);
};
const tabItems = cachingNodes.map((item: any) => ({
label: labelDropdown(item.name, item.tabName),
key: item.name,
closable: cachingNodes.length > 1,
}));
return (
<Tabs
hideAdd
size='middle'
type="editable-card"
className="base-tabs"
activeKey={pathname}
onTabClick={clickTab}
onEdit={editTab}
items={tabItems}
/>
);
};
// index.less
.base-tabs {
.ant-dropdown-trigger {
padding: 5px 10px;
height: 100%;
}
.dropdown-label {
padding: 5px 6px 5px 10px;
height: 100%;
}
.ant-tabs-tab {
padding: 0 !important;
}
.ant-tabs-tab-remove {
margin-left: 0 !important;
margin-right: 2px !important;
padding-left: 0px !important;
}
}
?4.修改路由
routes: [
{
name: '首頁(yè)',
path: '/home',
component: './Home',
},
{
name: '示例',
path: '/example',
routes: [
{
name: '權(quán)限演示',
path: '/example/access',
component: './Access',
wrappers: ['@/layouts/BaseLayout'],
},
{
name: ' CRUD 示例',
path: '/example/table',
component: './Table',
wrappers: ['@/layouts/BaseLayout'],
},
],
},
],
5.效果
到了這里,關(guān)于react umi/max 頁(yè)簽(react-activation)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!