react根据路由切换页面

本文介绍了一个使用React和Ant Design实现的可折叠侧边栏组件。该组件能够根据当前路径高亮显示相应的菜单项,并支持二级菜单。文章还展示了如何通过Redux管理组件状态以及如何与路由进行交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import * as React from 'react'
import { Menu } from 'antd'
import * as styles from './Aside.module.less'
import { DoubleRightOutlined,DoubleLeftOutlined } from '@ant-design/icons'

import routes from '../../../router'
import { RouteComponentProps, withRouter } from 'react-router-dom'
import { IMenuInfo } from 'src/types'
import { connect } from 'react-redux'
import actions from 'src/store/modules/common/actions'
// import { MenuGroup } from 'src/router/constant'
import 'src/assets/fonts/icon-font.css'

import { bindActionCreators } from 'redux'

const { SubMenu } = Menu

interface IState {
    pathname:string
}
interface ActionProps{
    actions: typeof actions,
    collapsed:boolean,
    authUrls: any[],
}

type IProps = RouteComponentProps<any>&ActionProps

const menuRoutes = routes.filter(item=>{return !item.hide})

class Aside extends React.Component<IProps, IState> {

    state:IState = {
        pathname:'',
    }

    // 点击菜单路由跳转
    handleClick = (menuItem: IMenuInfo, subMenuItem: IMenuInfo | undefined) => {
        const path = subMenuItem ? menuItem.path + subMenuItem.path : menuItem.path
        const { history } = this.props
        history.push({ pathname: path })
    }

    // 获取当前路径匹配的菜单
    getSelectedKey = (pathname: string): string[] => {
        const selectedParentNode = menuRoutes.find((item: IMenuInfo) => {
            let menuNode
            if (item.children) {
                // tslint:disable-next-line: no-unused-expression
                menuNode = (item.children && item.children.filter((subItem: IMenuInfo) => {
                    return item.path + subItem.path === pathname
                })) || []
                return menuNode.length > 0
            } else {
                return item.path === pathname
            }
        }) || menuRoutes[0]
        return [selectedParentNode.path]
    }

    toggleCollapsed = () => {
        this.props.actions.toggleMenuCollapsed()
    }

    unListen:any
    componentDidMount(){
        const { pathname } = this.props.location
        this.updatePathName(pathname)
        this.unListen = this.props.history.listen((listen:any)=>{
            const {pathname} = listen
            this.updatePathName(pathname)
        })
    }

    componentWillUnmount(){
        this.unListen&&this.unListen()
    }

    // 非菜单点击或者导航菜单没有的url 需要页面请求是高亮对应的项需要在本方法做处理
    /**
     * 更新pathname
     * @param pathname  当前变更的pathname
     */
    updatePathName = (pathname:string)=>{
        let pname = pathname
        if(['/intelligentSeat','/help'].includes(pathname)){
            pname = '/dashboard'
        }
        this.setState({
            pathname:pname,
        })
    }

    render() {
        
        const { collapsed, authUrls } = this.props
        const {pathname} = this.state
        const collapsedBtnStyle = { fontSize: '8px', verticalAlign: 'middle' }
        return (
            <div className={styles.aside}>
                <Menu
                    defaultSelectedKeys={[pathname]}
                    selectedKeys={[pathname]}
                    defaultOpenKeys={this.getSelectedKey(pathname)}
                    inlineCollapsed={collapsed}
                    mode="inline"
                    theme="light"
                >
                    {
                        menuRoutes.map((menuItem: IMenuInfo) => {
                            if (menuItem.children && menuItem.children.length > 0) {
                                if(authUrls.length && authUrls.includes(menuItem.path))
                                return (
                                    <SubMenu key={menuItem.path} title={menuItem.meta.title} icon={<span className={`iconfont ${menuItem.icon ||''}`}></span>}>
                                        {menuItem.children && menuItem.children.map((subMenuItem: IMenuInfo) => {
                                            if(!subMenuItem.hide){
                                                if(authUrls.length && authUrls.includes(menuItem.path + subMenuItem.path))
                                                return (
                                                    <Menu.Item
                                                        onClick={() => this.handleClick(menuItem, subMenuItem)}
                                                        key={menuItem.path + subMenuItem.path}
                                                    >
                                                        {subMenuItem.meta.title}
                                                    </Menu.Item>
                                                )
                                            }else{
                                                return null
                                            }
                                        })}
                                    </SubMenu>
                                )
                            } else {
                                if(authUrls.length && authUrls.includes(menuItem.path))
                                return (
                                    <Menu.Item
                                        onClick={() => this.handleClick(menuItem, undefined)}
                                        key={menuItem.path}
                                        icon={<span className={`iconfont ${menuItem.icon || ''}`}></span>}
                                    >
                                        {menuItem.meta.title}
                                    </Menu.Item>
                                )
                            }
                        })
                    }
                </Menu>
                <div className={styles.collaspeBtn} style={{width:collapsed?56:200}} onClick={this.toggleCollapsed}>
                    {collapsed ? <DoubleRightOutlined style={collapsedBtnStyle} /> : <DoubleLeftOutlined style={collapsedBtnStyle} />}
                </div>
            </div>
        )
    }
}

export default connect(
    (state: any) => {
        return {
            menuDisplay: state.commonReducer.menuDisplay,
            collapsed: state.commonReducer.collapsed,
            authUrls: state.login.authUrls,
        }
    },
    dispatch => {
        return {
            actions: bindActionCreators(actions, dispatch),
        }
    }
)(withRouter(Aside))

### React 中实现 Tab 路由切换React 应用程序中实现 Tab 路由切换可以通过多种方式完成。这里介绍一种基于 `react-router-dom` 和自定义组件的方式来创建一个功能完整的 Tab 切换机制。 #### 使用 `react-router-dom` 为了确保兼容性和稳定性,推荐使用最新稳定版本的 `react-router-dom`[^3]。以下是具体实现方法: 1. **安装依赖** 首先,在项目根目录下执行命令安装必要的库: ```bash npm install react-router-dom ``` 2. **设置路由配置** 创建文件 `App.js` 并编写如下代码片段: ```javascript import React from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; // 导入各个页面组件 import Home from './pages/Home'; import About from './pages/About'; import Users from './pages/Users'; function App() { return ( <Router> <div className="app"> {/* 渲染导航栏 */} <NavTabs /> {/* 定义不同路径对应的视图 */} <Switch> <Route exact path="/"> <Home /> </Route> <Route path="/about"> <About /> </Route> <Route path="/users"> <Users /> </Route> </Switch> </div> </Router> ); } export default App; ``` 3. **构建 Tab 组件** 接着,我们设计一个名为 `NavTabs` 的组件用于显示底部标签页并处理点击事件: ```javascript import React from 'react'; import { Link } from 'react-router-dom'; import styles from './navtabs.module.css'; // 假设有相应的 CSS 文件 const NavTabs = () => { const tabs = [ { label: "首页", to: "/" }, { label: "关于我们", to: "/about" }, { label: "用户列表", to: "/users" } ]; return ( <ul className={styles.tabs}> {tabs.map(({label, to}) => ( <li key={to} className={styles.tabItem}> <Link activeClassName={styles.active} to={to}>{label}</Link> </li> ))} </ul> ) }; export default NavTabs; ``` 上述代码通过遍历数组动态生成链接项,并利用 `activeClassName` 属性为当前激活状态下的选项添加特定类名以便于样式控制[^4]。 4. **应用样式调整** 最后一步是美化界面效果,可以新建 `.module.css` 文件定义所需样式规则: ```css /* navtabs.module.css */ .tabs { display: flex; justify-content: space-around; background-color: #f8f9fa; } .tabItem a { padding: .7em 0; color: inherit; text-decoration: none; } .tabItem a:hover, .tabItem a:focus { border-bottom: solid 2px blueviolet; } .tabItem .active { font-weight: bold; border-bottom: solid 2px tomato; } ``` 这样就完成了基本的功能开发流程,实现了带有高亮样式的多级菜单跳转逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值