Skip to content

Vgbire/react-keep-alive

Repository files navigation

安装

// npm
npm i @vgbire/react-keep-alive -S
// pnpm
pnpm i @vgbire/react-keep-alive -S
// yarn
yarn add @vgbire/react-keep-alive

Demo

1. Fork项目(🐶),git clone 到本地
2. pnpm i               //  如果没有需要装一下 pnpm
3. pnpm build           //  打包构建给example项目使用
4. npm run start -w example       // 运行查看示例项目

老的 CodeSandbox 示例项目

KeepAlive

基本功能描述

  • 实现 KeepAlive 组件缓存

  • 实现 useKeepAliveEffect 生命周期函数,会在组件激活时调用,可选择性返回一个 deactivated 函数,改函数会在组件失活时调用。

    Tip: 如果需要用到 useKeepAliveEffect 生命周期函数,需要使用 KeepAlveScope 包裹 KeepAlive 组件。

    import { KeepAliveScope, KeepAlive } from '@vgbire/react-keep-alive';
    ...
    const items = [
      { key: '1', children: <KeepAliveDemo1 /> },
      { key: '2', children: <KeepAliveDemo2 /> },
      { key: '3', children: <KeepAliveDemo3 /> },
    ];
    ...
    // 需要用到生命周期函数,则加上 KeepAliveScope
    // <KeepAliveScope>
    <KeepAlive activeKey={activeKey} items={items} />;
    // </KeepAliveScope>

KeepAlive 组件属性

activeKey?: string; // 当前激活组件的 Key
include?: string[]; // 只缓存需要缓存的路由组件的 Key
exclude?: string[]; // 排除不需要缓存的路由组件的 Key
max?: number; // 缓存的组件数量,默认 10
items?: Array<{ key: string; children: ReactNode }>; // 缓存的组件列表
styles?{
  wrapper?: CSSProperties; // 包裹元素的 style
  content?: CSSProperties; // 内容元素的 style
}

KeepAlive 生命周期函数

  • useKeepAliveEffect 在组件激活时执行,useKeepAliveEffect 返回的方法会在组件失活时执行。

  • 第二个可选参数是一个依赖项数组,为了更新回调函数里的依赖,一般不会用到,功能类似 useCallback,依赖变化不会执行函数。

    // KeepAliveDemo1 Code 生命周期函数使用示例
    import React, { useEffect } from 'react';
    import { useKeepAliveEffect } from '@vgbire/react-keep-alive';
    
    export const KeepAliveDemo1 = () => {
      useEffect(() => {
        console.log('KeepAlive Demo1');
      }, []);
      useKeepAliveEffect(() => {
        console.log('KeepAlive Demo1 激活了');
        return () => {
          console.log('KeepAlive Demo1 失活了');
        };
      });
      return <div>KeepAlive Demo1</div>;
    };

高级功能 - 路由缓存

alt text

基本功能描述

  • 标签式路由页面缓存,打开新路由新增一个标签,切换标签则切换到对应路由

  • 缓存路由页面,切换路由或者点击标签切换页面不会重新加载

  • 注意: 该功能需要用到react-router-dom V6.0/V7.0 + API,不支持react-router-dom V5.0及以下版本使用

  • 默认使用V7版本,如果项目使用的是V6版本,可以使用 changeVersion 将功能版本变更为 V6,否则会因为版本不一致报错

    // main.js
    import { changeVersion } from '@vgbire/react-keep-alive';
    changeVersion(6);

给 Layout 组件的 outlet 加上 keep-alive

// Layout.tsx
import { RouterKeepAlive, RouterTabs, RouterCache } from '@vgbire/react-keep-alive';
import { useOutlet } from 'react-router-dom';

const Layout = () => {
  // 需要使用useOutlet
  const outlet = useOutlet();

  return <RouterKeepAlive bodyStyles={{ wrapper: { padding: 20 } }}>{outlet}</RouterKeepAlive>;
  // 需要自定义时 RouterTabs 和 RouterCache 位置时
  // return (
  //   <RouterKeepAlive custom>
  //     <RouterTabs />
  //     <RouterCache styles={{ wrapper: { padding: 20 } }}>{outlet}</RouterCache>
  //   </RouterKeepAlive>
  // );
};

export default Layout;

路由定义需要增加 name、cache 属性(cache不配置默认开启缓存)

// router.ts
// 也可以是createHashRouter
import Layout form './Layout'

createBrowserRouter([
    {
        path: "/",
        element: <Layout />,
        loader: rootLoader
        children: [
            {
                path: "events",
                element: <Event />,
                // 增加name属性,否则标签没有title,展示出现问题
                // 如果不需要缓存可以配置cache false, 不配置或者true都会开启缓存
                handle: { name: "事件", cache: false},
            }
         ]
      }
]);

RouterKeepAlive 属性

  1. mode

    • path | search,默认为path
    • 默认匹配路由 path 决定,path 变化则会新增一个 tab,也就是如果查询参数变化不会新增一个 tab 缓存组件
    • 如果希望查询参数变化也会新增一个 tab 需要将 mode 改为 search
  2. nameKey:如果路由 name 已被占用,可以通过该字段获取 handle 下其他字段的信息作为 tab 的 title

  3. cacheMaxRemove

    • boolean,默认false
    • 缓存的 tab 数量超过 max 时,是否删除最开始缓存的 tab。true表示会删除。false会保留tab,但点击tab会重新加载组件
  4. theme: 主题颜色,提供 light 和 dark 两种主题色,默认为light

  5. size: 大小,提供 large middle 和 small 三种大小,默认为 middle

  6. custom: 默认为false,当需要自定义 RouterTabs 和 RouterCache 时,需要将其设置为true

  7. bodyStyles: 同 KeepAlive styles属性

    interface RouterKeepAliveProps {
      mode?: "path" | "search";
      nameKey?: string;
      cacheMaxRemove?: boolean;
      theme?: 'light' | 'dark';
      size?: 'small' | 'middle' | 'large';
      max?: number;
      custom?: boolean;
      bodyStyles?: {
        wrapper?: CSSProperties;
        content?: CSSProperties;
      };
    }

RouterKeepAlive 生命周期函数

useRouterEffect 用法同 useKeepAliveEffect

RouterKeepAlive 其他 API

  • close 方法用于关闭当前标签页
  • closeAll 用于关闭除了当前激活的 tab 所有的标签页
  • closeNavigator 是为了解决比如表单创建页,创建完之后需要跳转到其他路由。closeNavigator 会关闭当前创建页标签,然后跳转到指定路由。是 close()和 navigator(url)的语法糖。
import { useRouterKeepAliveApi } from '@vgbire/react-keep-alive';
...
  const { close, closeAll, closeNavigator } = useRouterKeepAliveApi();
...
  close()
  closeAll()
  // 是close()和navigator方法跳转到其他路由
  closeNavigator(url)
...

开发 & 调试

pnpm i
// 构建
npm run build
// 构建后运行example调试
npm run start -w example
// 发布
npm publish