在 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,讓項目看起來更加合理。