React + Router + Antd实现多标签页功能

写在前面

最近在学习React,并且开发一个类似于后台管理功能的前端项目,UI用的是阿里的ant design。在后台管理的项目中,其中一个比较实用的功能是多标签的模式,即点击不同菜单可以打开多个不同的Tab,并且点击Tab可以切换不同的页面内容,页面总体布局如下图:
在这里插入图片描述

在传统的jsp开发的年代,比较流行的一种多标签页的实现方式是用 iframe 实现多标签功能,不过由于iframe有着性能以及兼容性问题,网页上嵌套iframe的用法逐渐被抛弃。基于以上原因,项目中采用react router和antd组件的方式实现多标签功能。

具体实现

路由配置

项目中有两个主要组件,Login对应的是登录页面,Main对应的是主页面(即登录成功后跳转的页面),另外其他组件为具体的业务组件。在App.tsx中配置以下路由:

            <Provider store={store}>
                <HashRouter>
                    <Switch>
                        <Route path='/login' component={Login} ></Route>
                        <Route exact={false} path='/' component={Main} ></Route>
                    </Switch>
                </HashRouter>
            </Provider>

Login的配置比较简单,对应的路由是/login,即在访问/login时,显示login组件。
Main的路由中配置的路径为/,并且加了exact={false}的属性配置,即访问所有/路径下的子路径(当然除了/login),都会匹配至Main组件。
按以上路由配置时,实际实现的效果是访问/login,显示Login组件,访问/a,显示Main组件,访问/b,还是显示Main组件,另外访问除了/login地址之外的其他任何地址,都是显示Main组件,但是此时地址栏里的地址确实发生变化。

多Tabs标签页实现逻辑

实现逻辑比较简单:用户点击子菜单,首先需要做的是判断打开的tab中有无该菜单页面,有的话显示该tab,没有则添加tab并显示该新tab内容,tab功能比较简单,使用antd的Tabs标签页组件即可(Tabs标签页)。
而此时我们需要做的就是在Main组件中监控路由变化,并根据路由显示出具体的组件即可。

监听路由

React路由history对象提供了一个listen接口,文档如下:

export interface History<HistoryLocationState = LocationState> {
    length: number;
    action: Action;
    location: Location<HistoryLocationState>;
    push(path: Path, state?: HistoryLocationState): void;
    push(location: LocationDescriptor<HistoryLocationState>): void;
    replace(path: Path, state?: HistoryLocationState): void;
    replace(location: LocationDescriptor<HistoryLocationState>): void;
    go(n: number): void;
    goBack(): void;
    goForward(): void;
    block(prompt?: boolean | string | TransitionPromptHook<HistoryLocationState>): UnregisterCallback;
    listen(listener: LocationListener<HistoryLocationState>): UnregisterCallback;
    createHref(location: LocationDescriptorObject<HistoryLocationState>): Href;
}

listen接口参数listener监听方法参数中,其中一个参数为location,其中包含了访问路由地址等信息。listen监听方法中核心实现代码如下:

        this.props.history.listen((location, action) => {
            let {pathname} = location;
            const existFlag = this.props.tabs.findIndex((item: RouteDef) => item.path === pathname) >= 0;
            if (!existFlag) {
                // 添加tab,并显示tab组件内容
            } else {
                // 显示已存在的tab组件内容
            }
        });

另外需要特别考虑的一点就是如果访问的url对应的业务组件不存在,需要显示404页面,在此不展开来讲。
至此多标签功能基本上已完成。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值