react umi/max 页签(react-activation)

这篇具有很好参考价值的文章主要介绍了react umi/max 页签(react-activation)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

思路:通过react-activation实现页面缓存,通过umi-plugin-keep-alive将react-activation注入umi框架,封装页签组件最后通过路由的wrappers属性引入页面。

浏览本博客之前先看一下我的博客实现的功能是否满足需求,实现功能:

- 页面缓存
- 关闭当前页
- 阻止事件传播
- 鼠标右键>关闭当前
- 鼠标右键>关闭其他
- 鼠标右键>关闭左侧
- 鼠标右键>关闭右侧
- 鼠标右键>全部关闭(默认跳转到首页)
- 鼠标右键>重新加载(刷新缓存页面)

1.下载依赖

pnpm install react-activation@0.12.4

pnpm install umi-plugin-keep-alive@0.0.1-beta.35

2.修改.umirc.ts文件配置

import { defineConfig } from '@umijs/max';

export default defineConfig({
  plugins: ['umi-plugin-keep-alive'],
  ...
});

3.封装组件 

src目录下创建layouts文件夹,创建BaseLayout.tsx文件和BaseTabs.tsx、index.less文件文章来源地址https://www.toymoban.com/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();

  // 点击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);
      }
    }
  };

  // 关闭当前页
  const onCurrent = (e: any) => {
    let targetKey = JSON.parse(e?.key).name;
    dropScope(targetKey);
    // 关闭当前页面,需跳转到其他页签
    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);
      }
    }
  };

  // 关闭其他
  const onOther = (e: any) => {
    let targetKey = JSON.parse(e?.key).name;
    history.push(targetKey);
    clear();
  };

  //关闭左侧
  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 || '');
      }
    });
  };

  // 关闭右侧
  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 || '');
      }
    });
  };

  // 关闭全部
  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: '关闭当前',
                key: JSON.stringify({ name, key: 'current' }),
                disabled: cachingNodes.length <= 1,
                onClick: onCurrent,
              },
              {
                label: '关闭其他',
                key: JSON.stringify({ name, key: 'other' }),
                disabled: cachingNodes.length <= 1,
                onClick: onOther,
              },
              {
                label: '关闭左侧',
                key: JSON.stringify({ name, key: 'left' }),
                disabled: lastIndex === 0,
                onClick: onLeft,
              },
              {
                label: '关闭右侧',
                key: JSON.stringify({ name, key: 'right' }),
                disabled: lastIndex === cachingNodes.length - 1,
                onClick: onRight,
              },
              {
                label: '全部关闭',
                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: '首页',
      path: '/home',
      component: './Home',
    },
    {
      name: '示例',
      path: '/example',
      routes: [
        {
          name: '权限演示',
          path: '/example/access',
          component: './Access',
          wrappers: ['@/layouts/BaseLayout'],
        },
        {
          name: ' CRUD 示例',
          path: '/example/table',
          component: './Table',
          wrappers: ['@/layouts/BaseLayout'],
        },
      ],
    },
  ],

5.效果

react umi/max 页签(react-activation),第三方工具库,react.js,前端,前端框架

到了这里,关于react umi/max 页签(react-activation)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • umi/max如何给请求增加公共header

    直接上代码 根据 umi官网 介绍可知,umi/max仅提供一种运行时配置的方法。 如果是搭配typescript开发的话,最好使用@umi/max提供的RequestConfig类型进行字段控制。 因为是在app.ts中添加的配置,但是并不知道该配置是在何时何地如何被使用的,所以去翻阅了一下umijs/plugin-request源码

    2024年02月09日
    浏览(56)
  • React、Umi、RN 整体理解

    可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么? React 是用于构建用户界面的 JavaScript 库 ,起源于 Facebook 的内部项目,该公司对市场上所有 JavaScript MVC 框架都不满意,决定自行开发一套,用于架设 Instagr

    2024年02月05日
    浏览(58)
  • react umi中使用svg线上图片不加载问题

    参考链接: https://www.jianshu.com/p/c927122a6e82 前言: 在react项目中,我们本地通过img标签的src使用svg图片是可以加载的,但是发布到线上图片加载不出来。 解决方案 方案一 使用场景:直接在当前页面引入svg图片 有一个 svgr 插件,是支持以 react component 的方式,引入 svg 图片的。

    2024年02月11日
    浏览(38)
  • 微前端使用qiankun实现,react主应用同时兼顾react,vue3,umi子应用

    理解 :我们可以简单理解为微前端是将一个项目拆分成多个模块,每个微前端模块可以由不同的团队进行管理,并可以自主选择框架,并且有自己的仓库,可以独立部署上线 应用场景 :1.当公司代码较老需要使用新的技术栈时我们可以使用微前端。2.多个团队同时开发时,每

    2024年02月09日
    浏览(63)
  • react--umi, 根据权限展示菜单,完成页面权限分配,以及路由鉴权

           umi框架,prolayout布局,access设置菜单权限,initialState全局初始化数据,配合使用,根据后端返回的权限信息,完成菜单的不同的权限的不同展示。     1. umi 配合 patlayout 布局, 实现根据配置的路由展示菜单栏     2. umi 的 access 插件,设置不同权限的菜单展示    

    2024年02月06日
    浏览(91)
  • springboot的 spring.redis.lettuce的max-active、max-idle、min-idle的搭配

    在Spring Boot中,使用Lettuce作为Redis客户端是一种常见的选择。Lettuce是一个高性能、可扩展的异步Redis客户端。下面是关于 application.yml 配置文件中 spring.redis.lettuce 的一些配置: 配置项的含义: spring.redis.host 和 spring.redis.port :配置Redis服务器的主机名和端口号。 spring.redis.dat

    2024年02月12日
    浏览(37)
  • Python第三方库安装教程、什么是第三方库

    Python有一个全球社区:https://pypi.org/,在这里我们可以搜索任何主题的Python第三方库。PyPI全称是Python Package Index,指的是Python包的索引,它由PSF(Python Software Foundation)来维护,并且展示全球Python计算生态。 我们需要学会利用PyPI的主站检索,找到我们使用和关心的Python第三方

    2024年02月03日
    浏览(108)
  • 引入第三方字体库 第三方字体库Google Fonts

    googlefonts官方网站 googlefonts中国网站 本人是在微信小程序中引入 在static中建一个文件夹font-family 例如字体链接:https://fonts.font.im/css?family=Kirang+Haerang 将该链接的返回的资源的复制到css文件中 font-family.css main.js引入 微信小程序不校验合法域名就能看到结果

    2024年02月16日
    浏览(58)
  • Python第三方库安装——使用vscode、pycharm安装Python第三方库

    在这里介绍vscode、Pycharm安装python第三方库的方法。 操作系统:windows10 专业版 环境如下: Pycharm Comunity 2022.3 Visual Studio Code 2019 Python 3.8 pip:23.0.1 pycharm是一款很强大的、专用于写python的ide。 小白式安装第三方库往往能给初学者一种 “高级感” ,而对于使用惯了Linux的人而言

    2024年02月03日
    浏览(78)
  • Python第三方库批量下载到本地,并离线批量安装第三方库

    鉴于公司内网安装的python版本为python3.6.5,而此时又需要安装第三方库pytest,本来是想直接在Python官网PyPI直接搜对应可匹配跑python3.6.5版本的pytest进行下载然后传到内网安装即可,但是发现pytest依赖别的第三方库,根据报错装了几个依赖的第三方库之后,发现还是一堆的问题

    2024年02月07日
    浏览(94)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包