­

在 react-router 环境下使用 antd-mobile tabbar

本文阐述了如何在一个使用了 react-router 的 react 项目中合理的使用 antd-mobile tabbar 功能。在 antd-mobile 官方的例子中可以看到,只需要将不同的组件放置到每个 TabBar.Item 里面就可以了,这样就可以实现简单的切换效果,但是存在几个问题。

一个是切换过程中,路由是不会跟着切换的。比如我们想分享一个地址,当其他人打开这个地址时自动就跳转到第二个 tab 上。如果按上面的方法做是无法实现的。

另外一个问题是这样的设计不太符合大型项目的框架设计,我们往往会制作一些 layouts,给不同的组件匹配不同的 layout。如果按上面介绍的方法做,也是不好实现的。

综合以上两点问题,再加上 Google 了一些资料后,写下本文,以帮助更多遇到类似问题的人。

解决方案

首先定义四个路由分别指定不同的 component,要注意的是这四个路由都统一使用一个 layout,这也就解决了一些大型项目中分多种 layout 的问题。如下代码所示:

<Router history={browserHistory}>    {/* MainLayout 中包含了 antd-mobile tabbar */}    <Route path='/' component={MainLayout}>      {/* 默认跳转到 questions 页面 */}      <IndexRedirect to='/questions' />      <Route path='/questions' component={Questions} />      <Route path='/activities' component={Activities} />      <Route path='/videos' component={Videos} />      <Route path='/mine' component={Mine} />    </Route>  </Router>

随后我们看一下 mainLayout 的代码:

const MainLayout = ({children}) => {    const pathname = children.props.location.pathname      return (      <TabBar        unselectedTintColor='#949494'        tintColor='#33A3F4'        barTintColor='white'      >        <TabBar.Item          title='问答'          key='questions'          icon={<div className='questions-icon' />}          selectedIcon={<div className='questions-selected-icon' />}          selected={pathname === '/questions'}          onPress={() => {            browserHistory.push('/questions')          }}        >          { pathname === '/questions' ? children : null }        </TabBar.Item>        <TabBar.Item          title='活动'          key='activities'          icon={<div className='activities-icon' />}          selectedIcon={<div className='activities-selected-icon' />}          selected={pathname === '/activities'}          onPress={() => {            browserHistory.push('/activities')          }}        >          { pathname === '/activities' ? children : null }        </TabBar.Item>        <TabBar.Item          title='视频'          key='videos'          icon={<div className='videos-icon' />}          selectedIcon={<div className='videos-selected-icon' />}          selected={pathname === '/videos'}          onPress={() => {            browserHistory.push('/videos')          }}        >          { pathname === '/videos' ? children : null }        </TabBar.Item>        <TabBar.Item          title='我的'          key='mine'          icon={<div className='mine-icon' />}          selectedIcon={<div className='mine-selected-icon' />}          selected={pathname === '/mine'}          onPress={() => {            browserHistory.push('/mine')          }}        >          { pathname === '/mine' ? children : null }        </TabBar.Item>      </TabBar>    )  }

这里重点的代码就是 pathname === '/questions' ? children : null,根据当前路由判断加载不同的 component,并且在点击任何一个按钮的时候,自动跳转到指定的路由上。其中 selected 属性也根据路由动态的变换样式。路由传递给 mainLayout 是一个 children,这个 children 中就包含了组件的信息,我们根据路由的不同加载即可。

总结

这样处理后无论我们直接访问 URL 还是点击 tabbar 下面的任意按钮,不但可以切换页面,路由也会随之变动。最重要的是我们套用了 layout,让项目看起来更加合理。