[譯]不配置,不出事?Router Router v4那些坑(其一)

原文緩存

文中的一些名詞
路徑(path):指route上的參數path
路徑名(pathname):指location的路徑名異步

React Router 4與前代相比最大的變化莫過於其再也不須要配置。相對的,應用服務爲自身的"配置",並肯定渲染時該呈現的內容。這種新方式通暢運做良好,但仍是可能跳坑的。this

對比

首先咱們來回顧一下先前和如今的版本的工做流程上的區別。code

舊版本

以前,咱們須要配置一系列路由。你能夠自行定義對象來配置,也能夠經過<Route>組件來構建。component

<Router routes={{ path: '/', component: App, children: [...]}/>
// or
<Router>
  <Route path='/' component={App}>
    ...
  </Route>
</Router>

<Route>看似一個真正的組件,實則爲其參數服務。
當你寫出以下代碼:對象

<Route path='/' component={App}>
  <Route path='about' component={About}/>
</Route>

其實他等價於生命週期

React.createElement(
  Route,
  { path: '/', component: App },
  React.createElement(Route, { path: 'about', component: About })
)

React Router只關心從React元素中得到的屬性。路由

{
  path: '/',
  component: App,
  children: [
    { path: 'about', component: About}
  ]
}

一旦location變化,React Router會遍歷配置對象,來肯定新location匹配的路徑。爲了執行後續操做(如獲取數據,加載異步組件,限制訪問時的重定向),將會爲路由調用enter/update/exit方法。最終,對於匹配的路徑,依據路由的component參數來建立React元素。在當前路徑下,全部元素將被組合在一塊兒(經過this.props.children)並渲染出來。開發

如今的方式

第4代中,<Route>是一個真正的組件。當應用渲染時,路由(route)會將本身的路徑(path)與當前location的路徑名進行比較。若是匹配上,調用<Route>的render方法返回React元素,若是不匹配,則返回nullget

<Route path='/here' component={Here} />
// { pathname: "/here" }
return React.createElement(Here, { history, match, location })
// { pathname: "/elsewhere" }
return null

定義子路由時,子路由須要被放置在一個由父路由渲染的組件中([[譯註意]怎麼都以爲拗口,看代碼就清楚了)

const Child = () => <div>Child component</div>
const Parent = () => (
  <div>
    <h2>Parent component</h2>
    <Route path='/parent/child' component={Child}/>
  </div>
)
ReactDOM.render((
  <BrowserRouter>
    <Route path='/parent' component={Parent}/>
  </BrowserRouter>
), holder)

經過使用<Switch>組件,來建立分支點,這些點中只有一個的路由能匹配。這常被用於有多個路徑能夠匹配中同一個路徑名或須要一個'miss'組件對路徑所有匹配不上的狀況做處理。

即使不須要處理上述的情形,將路由放置於<Switch>組件中也是一個好方法,其既能夠保持路由邏輯又能夠獲得更明晰的DOM結構。

<Switch>
  <Route path='/the-good' component={Good}/>
  <Route path='/the-bad' component={Bad}/>
  <Route path='/the-ugly' component={Ugly}/>
</Switch>

React的生命週期方法能夠處理任意的enter/exit/update 調用。componentWillMountcomponentDidMount將處理enter,componentWillUpdate componentDidUpdate將處理update,componentWillUnmount將處理exit。

區別

4代的方式大大簡化了應用開發。經過React Router構建應用與常規React構建極其類似。有些內容你但願在特定的location下展現,你能夠將其放置於<Route>中。(從無路由的React應用能夠輕鬆改形成支持路由的應用)

然而無集中配置也純在一些問題。在你在渲染前須要確認被匹配的路由時,你會踩坑的。會出現如下問題:

  1. 全局的404頁面

  2. (批量) 數據獲取

  3. 帶有異步組件的服務端渲染

對於上述問題,一個路由配置能夠執行額外的步驟,以保證應用的正確渲染。

當"控制環節"在渲染步驟進行時,就不存在匹配路由與渲染她們的緩存區。這並不意味這些問題都被搞定了,這是變了個花樣罷了。

解決方法

在後續的章節,咱們會介紹在這些情形下,如何使用React Router v4去分析。他們並不必定給你解決方案,但能夠爲你指出正確的方向。請記住React Router v4還剛發佈不久。在不少方面它確實能作到開箱即用,但它也不是能適應全部場景的"萬能"庫。幸運的事,React擁有一個至關活躍的社區,並有不少人使用React Router。雖然須要一些時日,可是隨着愈來愈多的人使用React Router v4,將會有更多不一樣的解決方案被提出。若是你想出了一個好的解決方案,請把它分享出來。

相關文章
相關標籤/搜索