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;
相关推荐
fruge11 分钟前
前端自动化脚本:用 Node.js 写批量处理工具(图片压缩、文件重命名)
前端·node.js·自动化
Jolyne_26 分钟前
antd Image base64缓存 + loading 态优化方案
前端
BINGCHN32 分钟前
NSSCTF每日一练 SWPUCTF2021 include--web
android·前端·android studio
O***p60434 分钟前
JavaScript在Node.js中的集群负载均衡
javascript·node.js·负载均衡
Z***u6591 小时前
前端性能测试实践
前端
xhxxx1 小时前
prototype 是遗产,proto 是族谱:一文吃透 JS 原型链
前端·javascript
倾墨1 小时前
Bytebot源码学习
前端
用户93816912553601 小时前
VUE3项目--集成Sass
前端
S***H2831 小时前
Vue语音识别案例
前端·vue.js·语音识别
啦啦9118862 小时前
【版本更新】Edge 浏览器 v142.0.3595.94 绿色增强版+官方安装包
前端·edge