react+anddesign组件Tabs实现后台管理系统自定义页签头

使用react和anddesign开发一个后台管理页签头。这里使用全局状态管理zustand来实现这个功能。

安装zustand

javascript 复制代码
npm install zustand --save

创建store文件夹并在文件夹下创建useTabs.ts文件

javascript 复制代码
// useTabs.ts
import { create } from 'zustand'

interface tabLiSTState {
  tabList: Array<any>, // 页签头数据
  setTabList: (tabs: Array<any>) => void // 添加tabs全局方法
}

export const useTabs = create<tabLiSTState>((set) => ({
  tabList: [{ title: "首页", path: '/' }],
  setTabList: (tabs) => set({ tabList: tabs }),
}))

创建Tabs组件组件

使用useEffect监听路由的变化,路由变化调用添加页签方法把当前菜单名称title和路径添加到全局状态管理中

javascript 复制代码
import { useState, useEffect } from 'react'
import { Tabs } from 'antd'
import { useLocation, useNavigate } from 'react-router-dom'
import { routerArray } from '@/router/routes'
import MoreButton from './components/MoreButton'
import { useTabs } from '@/store/useTabs'
import './index.scss'
import { searchRoute } from '@/utils'
const LayoutTabs = () => {
  const { pathname } = useLocation()
  const navigate = useNavigate();
  const [activeTabs, setActiveTabs] = useState(pathname)
  const { tabList, setTabList } = useTabs()
  // 监听路由变化
  useEffect(() => {
    addTabs()
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pathname])
  const clickTabs = (path: string) => {
    navigate(path)
  }
  // 添加tabs
  const addTabs = () => {
    const route = searchRoute(pathname, routerArray)
    const newTabList = JSON.parse(JSON.stringify(tabList))
    if(tabList.every(item => item.path !== pathname)) {
      newTabList.push({
        title: route.meta!.title,
        path: route.path,
      })
    }
    setTabList(newTabList)
    setActiveTabs(pathname)
  }
  // 关闭tabs
  const closeTabs = (path) => {
    if(path === '/') return
    if(pathname === path) {
      tabList.forEach((item, index) => {
        if(item.path !== path) return
        const nextTab = tabList[index + 1] || tabList[index - 1]
        if(!nextTab) return
        navigate(nextTab.path)
      }) 
    }
    setTabList(tabList.filter(item => item.path !== path))
  }
  const item = tabList.map((i) =>{
    return {
      label: i.title,
      key: i.path,
      closable: i.path !== '/'
    }
  })
  return (
    <div className='tabs'>
      <Tabs
        animated
        hideAdd
        type="editable-card"
        activeKey={activeTabs}
        onChange={clickTabs}
        onEdit={closeTabs}
        items={item}
      />
      <MoreButton tabList={tabList} closeTabs={closeTabs} setTabList={setTabList} />
    </div>
  )
}

更多操作

主要是一些重新加载、关闭当前标签页、关闭左侧、关闭右侧、关闭其它、关闭所有

MoreButton组件

javascript 复制代码
import { DownOutlined } from '@ant-design/icons';
import { useLocation, useNavigate } from 'react-router-dom'
import { Dropdown } from 'antd';

const MoreButton = (props) => {
  const { pathname } = useLocation()
  const navigate = useNavigate();

  // 关闭左侧
  const closeLeftTabs = () => {
    const activeIndex = props.tabList.findIndex(item => item.path === pathname)
    const newTabs = props.tabList.filter((_, index) => index >= activeIndex || _.path === '/')
    props.setTabList(newTabs)
  }
  // 关闭右侧
  const closeRightTabs = () => {
    const activeIndex = props.tabList.findIndex(item => item.path === pathname)
    const newTabs = props.tabList.filter((_, index) => index <= activeIndex)
    props.setTabList(newTabs)
  }
  // 关闭其它
  const closeOtherTabs = () => {
    const list = props.tabList.filter(item => item.path === pathname || item.path === '/')
    props.setTabList(list)
  }
  // 关闭所有
  const closeAllTabs = () => {
    const list = props.tabList.filter(item => item.path === '/')
    props.setTabList(list)
    navigate('/')
  }
  const items = [
    {
      key: '1',
      label: '重新加载',
      onClick: () => {
        window.location.reload();
      }
    },
    {
      key: '2',
      label: '关闭当前',
      onClick: () => {
        return props.closeTabs(pathname)
      }
    },
    {
      key: '3',
      label: '关闭左侧',
      onClick: closeLeftTabs
    },
    {
      key: '4',
      label: '关闭右侧',
      onClick: closeRightTabs
    },
    {
      key: '5',
      label: '关闭其它',
      onClick: closeOtherTabs
    },
    {
      key: '6',
      label: '关闭所有',
      onClick: closeAllTabs
    },
  ];
  return (
    <Dropdown.Button
      className='moreButton'
      icon={<DownOutlined />}
      menu={{ items }}
      type="primary"
    >
      更多
    </Dropdown.Button>
  );
}

export default MoreButton;
相关推荐
小红帽6152 小时前
Web服务器(Nginx和Apache)
服务器·前端·nginx
小高0072 小时前
💥写完watchEffect就下班?小心组件半夜给你“暴雷”!
前端·javascript·vue.js
懒大王、2 小时前
视频元素在富文本编辑器中的光标问题
前端·vue.js
用户0751420429052 小时前
Docker 一键部署 NestJS + MySQL 避坑指北
前端
xianyinsuifeng2 小时前
概念篇:ReactJS + AppSync + DynamoDB 性能优化核心概念
前端·react.js·性能优化·aws
OEC小胖胖2 小时前
SEO 优化:元数据 (Metadata) API 和站点地图 (Sitemap) 生成
前端·javascript·前端框架·html·web·next.js
Bruce-li__2 小时前
前端开发利器:nvm、npm与pnpm全面解析与TypeScript/JavaScript选择指南
javascript·typescript·npm
Dontla2 小时前
npx命令介绍(Node Package Execute)(允许开发者直接执行来自npm注册表的包中的二进制文件,而无需全局安装)临时使用
前端·npm·node.js
张人玉2 小时前
npm和pnpm命令大全
前端·npm·node.js