ant-design-pro项目路由组件缓存keep-alive

如图,要实现的功能,将已点击过的菜单展示在顶部的tabs中,切换tab内容缓存.删除tab后清除页面缓存,点击菜单再打开是新页面

 

实现:
使用的是react-activation,其中有umijs的实现demo

 

官网地址https://www.npmjs.com/package/react-activation

1. 安装 yarn add umi-plugin-keep-alive

2. 在页面的通用组件里,一般是包裹所有页面组件的layout中添加
 

 

主要看标红的部分,其他是tabs的实现
commonLayout.tsx
import React, { useEffect, useState } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import { history, useModel } from 'umi';
import { find } from 'lodash';
import type { menuTabProps } from '@/services/types';
import { handleMenusToFlat } from '@/utils/base';
import { KeepAlive, useAliveController } from 'react-activation';

const CommonLayout: React.FC = (props: any) => {
  const { location, route } = props;
  const { pathname } = location;
  const [activeKey, setActiveKey] = useState<string>('');
  const { dropScope } = useAliveController();
  const { exitMenus, updateMenus } = useModel('exitMenus', (model) => ({
    exitMenus: model.exitMenus,
    updateMenus: model.updateMenus,
  }));

  const flatMenus = handleMenusToFlat(route.routes);
  const noCachRoutes = ['/', '/user/login']; // 不需要缓存的路由

  useEffect(() => {
    // console.log(333, location, flatMenus);
    if (noCachRoutes.includes(pathname)) return;
    const arr: menuTabProps[] = exitMenus.filter((item: menuTabProps) => item.key !== pathname);
    if (arr.length === exitMenus.length) {
      const activeTab = find(flatMenus, (item) => item.pathname === pathname) || {};
      const activeMenu: menuTabProps = {
        tab: activeTab.name,
        key: pathname,
        closable: exitMenus.length > 0, // 新增时,第一个页面不能删除
      };
      arr.push(activeMenu);

      updateMenus(arr);
    } else if (exitMenus.length === 1) {
      // 删除时,只剩一个标签去掉删除图标
      const data = exitMenus;
      data[0].closable = false;
      updateMenus(data);
    }
    setActiveKey(pathname);
  }, [location]);

  const onTabChange = (key: string) => {
    history.push(key);
    setActiveKey(key);
    // console.log(key);
  };
  return (
    <PageContainer
      tabList={exitMenus}
      onTabChange={onTabChange}
      header={{
        title: null,
      }}
      tabProps={{
        type: 'editable-card',
        hideAdd: true,
        activeKey,
        tabBarStyle: {
          paddingBottom: '3px',
        },
        onEdit: (path: string) => {
          // console.log(path, exitMenus, pathname);
          let activePath = pathname;
          const arr: menuTabProps[] = exitMenus.filter((item: menuTabProps, i: number) => {
            if (item.key === path) {
              // 获取前一个标签
              activePath = exitMenus[i - 1].key;
            }
            return item.key !== path;
          });
          // 如果关闭当前标签,展示前一个标签
          if (path === pathname) {
            history.push(activePath);
          }
          // 关闭页签去掉缓存
          dropScope(path);
          updateMenus(arr);
        },
      }}
    >
      <KeepAlive 
        when={true} //组件卸载后缓存(离开页面时缓存)可以传入Boolean,array,function
        id={pathname} // 缓存多个页面时要有id
        name={pathname} // 页面的path地址
        saveScrollPosition="screen" // 可以记住页面的滚动位置,切换页面是回到上一次滚动的位置,可以设置为false
      >
        {props.children}
      </KeepAlive>
    </PageContainer>
  );
};

export default CommonLayout;
这样就实现路由的缓存了,其他地方不需要改动
posted @ 2022-07-06 16:09  潇湘羽西  阅读(3872)  评论(0编辑  收藏  举报