ant design pro多页签功能

效果:

原理:
1、所有需要页签页面,都需要一个共同父组件

2、如何缓存,用的是ant的Tabs组件,在共同父组件中,实际是展示的Tabs组件

3、右键,用的是ant的Dropdown组件,当点击时,记录所对应的key值及坐标,做后续操作

代码:

1、路由处理,需要用一个共同的父组件

在ant design pro4中,不支持隐藏父路由,展示子路由的功能,需要在app.tsx文件中,对路由做额外处理

共同父组件,BaseLayout.tsx文件,记录所有路由组件,在tab中展示。在不同版本的ant design pro中,props提供的路由组件的值会有差别

import {useEffect, useRef, useState} from "react";
import {Tabs} from "antd";
import { history } from 'umi';
import RightMenu from "@/components/RightMenu";
import './baseLayout.less'const BaseLayout = (props: any) => {const [activeTab, setActiveTab] = useState<any>('');const [nodeKey, setNodeKey] = useState('')const [tabItems, setTabItems] = useState<{name: string,pathname: string}[]>([]);const pathname = props.location.pathnameconst refPathObj = useRef<any>({})const refRightMenu = useRef<any>(null)const refLastPath = useRef<any>('')const setPathObj = (list: any[]) => {list.forEach((v: any) => {if (v.routes) {setPathObj(v.routes)} else if (!v.redirect) {const C = v.componentrefPathObj.current[v.path] = {name: v.name,component: <C />}}})}// 获取默认路由useEffect(() => {const routes = props.route.routes || []setPathObj(routes)}, []);// 更新tab列表useEffect(() => {const currtabItem = {name: refPathObj.current?.[pathname]?.['name'],pathname,};const isReplace = props.history.action === "REPLACE"const lastPath = refLastPath.currentif (pathname !== '/') {setTabItems((prev) => {let next = prev.find((item) => item.pathname === pathname)? prev: [...prev, currtabItem];// 如果是replace,则隐藏上一个if (isReplace) {next = next.filter((v) => v.pathname !== lastPath)}return next.slice(-5)});setActiveTab(pathname)} else {history.push('/orderManage')}refLastPath.current = pathname}, [pathname]);const clickMouseRight = (e: any) => {const $target = e.targetconst left = e.clientXconst top = e.clientYconst getNodeKey: any = (el: any) => {const nKey = el.getAttribute('data-node-key')if (nKey) {return nKey}return getNodeKey(el.parentNode)}const nKey = getNodeKey($target)setNodeKey(nKey)refRightMenu.current.setShow(true)refRightMenu.current.setStyle({left, top})}// 右击事件useEffect(() => {const right: any = document.querySelector('.base-layout-tab-menu');if (!right) return () => {}const $tabBox = right.children[0].children[0].children[0]$tabBox!.oncontextmenu = function(e: any){e.preventDefault();clickMouseRight(e)};return () => {$tabBox!.oncontextmenu = null}}, []);const removeTab = (targetKey: any) => {const next = tabItems.filter((v) => {return v.pathname !== targetKey})setTabItems(next)if (activeTab === targetKey) {history.push(next[next.length-1].pathname)}};const clickRightMenu: any = (p: any) => {const key = p.keyswitch (key) {case 'current':removeTab(nodeKey)breakcase 'other':setTabItems(prev => {const next = prev.filter((v) => {return v.pathname === nodeKey})history.push(nodeKey)return next})break}refRightMenu.current.setShow(false)}const rightMenuItem = [{key: 'current',label: '关闭',disabled: tabItems.length <= 1,onClick: clickRightMenu},{key: 'other',label: '关闭其它',disabled: tabItems.length <= 1,onClick: clickRightMenu}]return <><TabsclassName={'base-layout-tab-menu'}type="editable-card"hideAddonChange={(activeKey) => {history.push(activeKey)setActiveTab(activeKey)}}activeKey={activeTab}onEdit={removeTab}>{tabItems.length > 0 &&tabItems.map((tabItem) => {return (<Tabs.TabPanetab={tabItem.name}key={tabItem.pathname}closable={tabItems.length > 1}>{/* 替换原来直接输出的 children */}{refPathObj.current[tabItem.pathname]['component']}</Tabs.TabPane>);})}</Tabs>{/*{ props.children }*/}<RightMenuref={refRightMenu}items={rightMenuItem}/></>
}BaseLayout.displayName = 'BaseLayout'
export default BaseLayout

自定义右键操作,RightMenu.tsx文件

import React, {FC, useEffect, useImperativeHandle, useState} from "react";
import {Dropdown} from "antd";
import './index.less'interface IProps {ref: anyitems: {key: string,label: string,onClick: any}[]
}const RightMenu: FC<IProps> = React.forwardRef((props, ref) => {const [visible, setVisible] = useState(false)const [sty, setSty] = useState<{left: number,top: number}>({left: 0, top: 0})const {items} = propsuseEffect(() => {const fn = function () {setVisible(false)}document.addEventListener('click', fn)return () => {document.removeEventListener('click', fn)}}, []);const setShow = (b: boolean) => {setVisible(b)}const setStyle = (s: any) => {setSty(s)}useImperativeHandle(ref, () => ({setShow,setStyle}))return <><Dropdownmenu={{ items }}open={visible}><spanclassName={'right-menu-holder'}style={{...sty,display: visible ? 'block' : 'none',}}>&nbsp;</span></Dropdown></>
})RightMenu.displayName = 'RightMenu'
export default RightMenu

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/870438.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在linux中查找 / 目录下的以.jar结尾的文件(find / -name *.jar)

文章目录 1、查找 / 目录下的以.jar结尾的文件 1、查找 / 目录下的以.jar结尾的文件 [rootiZuf6332h890vozldoxcprZ ~]# find / -name *.jar /etc/java/java-1.8.0-openjdk/java-1.8.0-openjdk-1.8.0.342.b07-1.el9_0.x86_64/lib/security/policy/limited/US_export_policy.ja…

【学习css2】grid布局-页面footer部分保持在网页底部

中间内容高度不够屏幕高度撑不开的页面时候&#xff0c;页面footer部分都能保持在网页页脚&#xff08;最底部&#xff09;的方法 1、首先上图看显示效果 2、奉上源码 2.1、html部分 <body><header>头部</header><main>主区域</main><foot…

在 Linux 上设置 RAID 阵列的全面指南

引言 在这篇博文中&#xff0c;我们将深入探讨如何在 Linux 上设置 RAID 阵列。本文将涵盖 RAID 的定义、架构、原理、应用场景、常见命令体系&#xff0c;并通过详细的实战模拟展示如何在 Linux 系统上实际操作。希望通过这篇文章&#xff0c;您能深入理解 RAID 技术&#xff…

Flutter实现局部刷新的几种方式

目录 前言 1.局部刷新的重要性 1.概念 2.重要性 2.局部刷新实现的几种方式 1.使用setState方法进行局部刷新 2.使用StatefulWidget和InheritedWidget局部刷新UI 3.ValueNotifier和ValueListenableBuilder 4.StreamBuilder 5.Provider 6.GetX 7.使用GlobalKey 前言 …

现在有什么副业可以让人快速上岸?可以试试这个行业上岸其实不难

人为什么要努力赚銭&#xff1f; 当你想结婚的时候&#xff0c; 你可以慢慢挑&#xff0c;不着急。 当父母年老遭遇大病的时候&#xff0c; 你有机会尽孝。 当孩子需要时&#xff0c;你不会囊中羞涩。 年轻时以为金钱最重要&#xff0c; 如今年纪大了&#xff0c;发现这…

CSS在页面中使用的三种方式:行内样式、内嵌式样式表、链接式样式表

CSS样式如何在页面中使用&#xff0c;包含三种方式&#xff1a;行内样式、内嵌式样式表、链接式样式表。 1、行内样式 行内样式是比较直接的一种样式&#xff0c;直接定义在 HTML 标签之内&#xff0c;并通过 style 属性来实现。这种方式比较容易学习&#xff0c;但是灵活性不…

【秋招突围】2024届秋招笔试-字节跳动笔试题-01-三语言题解(Java/Cpp/Python)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 ✨ 本系列打算持续跟新 秋招笔试题 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f4e7; 清隆这边最…

【Python 基础】控制流 - 2

程序执行 在第1篇的 hello.py 程序中,Python 开始执行程序顶部的指令,然后一条接一条往下执行。“程序执行”(或简称“执行”)这一术语是指当前被执行的指令。如果将源代码打印在纸上,在它执行时用手指指着每一行代码,你可以认为手指就是程序执行。 但是,并非所有的程…

Python基础知识——(004)

文章目录 P16——15. 布尔类型 P17——16. 类型转换函数 P18——17. eval函数 P19——18. 算数运算符 P20——19. 赋值运算符 P16——15. 布尔类型 布尔类型 用来表示 “真” 值或 “假” 值的数据类型在Python中使用标识符 True 或 False 表示布尔类型的值True表示整数1&…

【vue】下载 打印 pdf (问题总结)- 持续更新ing

这里是目录标题 一、pdf1.查看 下载一、pdf 1.查看 下载 样式 Code<template><div><el-table :data="pdfList" style="width: 100%" border ><el-table-columnprop="index"label="序号"width="80"ali…

【UE5.1】NPC人工智能——01 准备NPC角色

效果 步骤 1. 之前我们已经创建了“BP_NPC”&#xff08;见&#xff1a;【UE5.1 角色练习】06-角色发射火球-part2&#xff09; 该蓝图继承于角色类 我们在该蓝图中添加了两个方法和两个变量。方法一个是用于修改角色HP值的&#xff0c;另一个是在收到伤害后执行的逻辑。两个…

面试题005-Java-JVM(上)

面试题005-Java-JVM(上) 目录 面试题005-Java-JVM(上)题目自测题目答案1. JVM由哪几部分组成&#xff1f;2. 运行时数据区中包含哪些区域&#xff1f;3. 栈和堆中分别存放什么数据&#xff1f;4. 为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) &#xff1f;5. 堆空间的…

千万慎投!自引率高达93%!这16本On hold正处于高危状态,无法检索,剔除岌岌可危中!近四年镇压期刊“出狱”情况一览

本周投稿推荐 SCI • 能源科学类&#xff0c;1.5-2.0&#xff08;25天来稿即录&#xff09; • CCF推荐&#xff0c;4.5-5.0&#xff08;2天见刊&#xff09; • 生物医学制药类&#xff08;2天逢投必中&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09…

20240712 每日AI必读资讯

&#x1f4f0;人工智能现状报告最新重要发现&#xff01;&#xff01; - 国外软件开发平台 Retool 日前调查约 750 位技术人员发现&#xff0c;AI 的采用率并没有飙升&#xff0c;但工作岗位的替代危机正在上演。 - AI 的采用率真的在飙升吗&#xff1f;真实现状&#xff1a;…

缓冲器的重要性,谈谈PostgreSQL

目录 一、PostgreSQL是什么二、缓冲区管理器介绍三、缓冲区管理器的应用场景四、如何定义缓冲区管理器 一、PostgreSQL是什么 PostgreSQL是一种高级的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它以其稳定性、可靠性和高度可扩展性而闻名。它最初由加…

sqli-labs2

sqli-labs2 1.按照路径http://localhost/sqli-labs/sqli-labs-master/Less-2/进入 2.确认注入类型----数字型 Payload&#xff1a;?id1 and 11-- 3. 判断注入点&#xff1a;2&#xff0c;3 Payload&#xff1a;id-1 union select 1,2,3 -- 4.根据注入点查询数据库名----sec…

防火墙基础实验

首先交换机配置 [LSW7]undo info-center enable [LSW7]vlan batch 2 3 [LSW7]int g0/0/2 [LSW7-GigabitEthernet0/0/2]port link-type access [LSW7-GigabitEthernet0/0/2]port default vlan 2 [LSW7-GigabitEthernet0/0/2]int g0/0/3 [LSW7-GigabitEthernet0/0/3]port link-…

码云远程仓库, 回滚到指定版本号

1. 打开项目路径, 右击Git Bash Here 2. 查找历史版本 git reflog 3. 回退到指定版本 git reset --hard 版本号 4. 强制推送到远程 git push -f

#VERDI# 关于如何查看FSM状态机的方法

关于Verdi中查看状态机的问题,想必大家都duniang 一大把资料可以看,今天,主要在前人讲解的基础之上,这里添加一些自己的心得体会。为什么呢? 说来惭愧,自己工作几个年头了,但是对于Verdi中查查看状态机,还是心里有一些抵触。 今天,花点时间整理一下分享大家,如有不…

windows上修改redis端口号

概况 redis是一个开源的内存数据结构存储系统&#xff0c;常用做数据库、缓存和消息代理。默认的端口号为6379 更改redis端口号步骤如下 先停止redis服务 redis-cli shutdowm 打开redis配置文件 在redis安装目录下&#xff0c;即redis.windows.conf文件。 port 6396 然后…