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;
相关推荐
八月ouc几秒前
每日小知识点:10.14 webpack 有几种文件指纹
前端·webpack
苏琢玉4 分钟前
从 Hexo 到 Astro:重构我的个人博客
前端·hexo
Glommer7 分钟前
某音 Js 逆向思路
javascript·逆向
街尾杂货店&10 分钟前
webpack - 单独打包指定JS文件(因为不确定打出的前端包所访问的后端IP,需要对项目中IP配置文件单独拿出来,方便运维部署的时候对IP做修改)
前端·javascript·webpack
月光技术杂谈12 分钟前
用Deepseek 实现一个基于web的扣图应用
前端·javascript·html5·ccs·tensorflow.js·canvas api
金梦人生1 小时前
Css性能优化
前端·css
Holin_浩霖1 小时前
UI设计的底层逻辑:从组件到系统的跃迁
前端
Holin_浩霖1 小时前
前端开发者的 Web3 全图解实战 二
前端
写代码的皮筏艇1 小时前
CSS属性继承与特殊值
前端·css
kevlin_coder1 小时前
🚀 实现同一个滚动区域包含多个虚拟滚动列表
前端·javascript