
使用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;