2019-08-11

react-router4的好處究竟在哪里

最近被人問(wèn)到你的項(xiàng)目中為什么要使用react-router v4,瞬間有點(diǎn)懵逼?;卮鹫f(shuō),幫我們實(shí)現(xiàn)路由啊,被反問(wèn),僅僅是為了幫助實(shí)現(xiàn)路由嗎,自己也可以手寫(xiě)一套路由啊,沒(méi)有什么難度啊,為什么要使用別人的呢。當(dāng)他問(wèn)到這的時(shí)候,我就知道問(wèn)到盲區(qū)了。于是晚上空閑的時(shí)候我仔細(xì)研究和查閱了一下,說(shuō)實(shí)話,react-router不知道已經(jīng)用了多少次了??梢哉f(shuō),里面的源碼我都已經(jīng)吃透了,但是竟然從來(lái)沒(méi)有想過(guò)react-router的優(yōu)點(diǎn)在哪里,這點(diǎn)確實(shí)是值得反思的

react-router v4與react-router v3的比較

查閱文檔及翻看博客發(fā)現(xiàn),React Router v4 最大的變更,不是API的變更,而是從靜態(tài)路由到動(dòng)態(tài)路由的變化。什么是靜態(tài)路由呢?靜態(tài)路由是一堆在應(yīng)用運(yùn)行前就已經(jīng)定義好的路由配置,應(yīng)用需要在啟動(dòng)時(shí),加載這些配置,構(gòu)建出整個(gè)應(yīng)用的路由表,然后當(dāng)接收到某一請(qǐng)求時(shí),根據(jù)請(qǐng)求地址,到應(yīng)用路由表中找到對(duì)應(yīng)的處理頁(yè)面或處理方法。就是說(shuō)路由一定要集中配置,沒(méi)有集中配置的路由無(wú)法找到匹配頁(yè)面。不管是前端開(kāi)發(fā),還是后端開(kāi)發(fā),只要涉及到路由,大部分情況下,其實(shí)我們使用的都是靜態(tài)路由。例如,React Router v3版本中,我們會(huì)配置一個(gè)類似下面形式的路由:

<Router history={browserHistory}>
  <Route path='/' component={login}>
    <Route path='about' component={About}>
    <Route path='contact' component={Contact}>
    // ...
  </Route>
</Router>

它的基本工作流程是:Router組件根據(jù)所有的子組件Route,生成全局的路由表,路由表中記錄了path與UI組件的映射關(guān)系,然后Router監(jiān)聽(tīng)path的變化,當(dāng)path變化時(shí),根據(jù)新的path,找出對(duì)應(yīng)的component,按一定層級(jí)將這些UI組件渲染出來(lái)。
這種方式看起來(lái)簡(jiǎn)單明了,理解起來(lái)也非常的輕松。但是這種實(shí)現(xiàn)方式是違背了react的組件化思想的。react提倡一切皆組件,組件是什么,對(duì)應(yīng)到頁(yè)面上它就是頁(yè)面的一部分,也就是UI。但是,v3的route組件只是包了一層react的殼子,實(shí)際上它并沒(méi)有渲染組件,這點(diǎn)我們可以通過(guò)它的源碼就可以看出來(lái):

const Route = createReactClass({
  // 省略無(wú)關(guān)代碼
  /* istanbul ignore next: sanity check */
  render() {
    invariant(
      false,
      '<Route> elements are for router configuration only and should not be rendered'
    )
  }
})

可以發(fā)現(xiàn)render里面并沒(méi)有渲染任何東西,所以說(shuō)它不是傳統(tǒng)意義上的react組件。當(dāng)然,router的開(kāi)發(fā)者也意識(shí)到了這個(gè)問(wèn)題,所以在v4中,對(duì)React Router 進(jìn)行了重寫(xiě),將Route作為普通React組件看待,每個(gè)Route也負(fù)責(zé)UI的渲染工作,讓React Router在React的大框架下運(yùn)轉(zhuǎn)。我們用v4版本實(shí)現(xiàn)一個(gè)路由:

<BrowserRouter>
            <Switch>
              <Route exact path="/login" render={() => <LoginView />} />
              <Route
                path="/:tabIndex/:module"
                render={() => <HomeComponent />}
              />
              <Route
                path="/"
                render={() => <RedirectComponent moduleName="community" />}
              />
            </Switch>
</BrowserRouter>

看起來(lái)寫(xiě)法跟上面的那個(gè)例子沒(méi)有什么大的區(qū)別,所以說(shuō)它這個(gè)路由升級(jí)還是比較友好的。但是深層次的東西是有巨大的改變的,我們?cè)賯z看一下route的實(shí)現(xiàn):

class Route extends React.Component {
  //...省略無(wú)關(guān)代碼
  render() {
    const { match } = this.state
    const { children, component, render } = this.props
    const { history, route, staticContext } = this.context.router
    const location = this.props.location || route.location
    const props = { match, location, history, staticContext }

    return (
      component ? ( // component prop gets first priority, only called if there's a match
        match ? React.createElement(component, props) : null
      ) : render ? ( // render prop is next, only called if there's a match
        match ? render(props) : null
      ) : children ? ( // children come last, always called
        typeof children === 'function' ? (
          children(props)
        ) : !Array.isArray(children) || children.length ? ( // Preact defaults to empty children array
          React.Children.only(children)
        ) : (
          null
        )
      ) : (
        null
      )
    )
  }
}

可以發(fā)現(xiàn)每一個(gè)router對(duì)應(yīng)的都會(huì)渲染對(duì)應(yīng)的組件,macth方法會(huì)自動(dòng)給我們計(jì)算,如果沒(méi)有匹配的。則返回一個(gè)null。這種模式的路由就是動(dòng)態(tài)路由。可見(jiàn),動(dòng)態(tài)路由發(fā)揮作用的時(shí)間是在組件渲染時(shí),而不是通過(guò)提前配置的方式,在應(yīng)用剛收到請(qǐng)求時(shí),就已經(jīng)知道該渲染哪些組件了。
從上面的分析,可以得出動(dòng)態(tài)路由的一個(gè)優(yōu)點(diǎn)是,它會(huì)同時(shí)負(fù)責(zé)UI的渲染工作,而不是單純的路由配置工作。此外,動(dòng)態(tài)路由的另外一個(gè)優(yōu)點(diǎn)是,你可以在任意時(shí)間、任意地點(diǎn)自由添加新的Route。例如,在上面的例子中,我想在后面定義更多的頁(yè)面,你想在哪都可以,在主頁(yè)面或者其他地方都可以,它會(huì)將route匹配渲染的組件作為當(dāng)前組件的一部分進(jìn)行渲染。非常的方便,下面是一個(gè)例子:

class Layout extends React.Component {
render(){ return
    (<div className="Layout-content">
        <div className="Layout-header-part">
          <div className="header-right-part">
            <MenuList
              menuList={menuList}
              activeMenu={activeMenu}
              menuClick={this.menuClick.bind(this)}
            />
            <UserAction
              //userInfo={UserStore.userInfo}
              userPopTolls={this.userPopTolls}
              logOut={this.logOut.bind(this)}
              showAlarmAction={this.showAlarmAction.bind(this)}
              clickPopAction={this.clickPopAction.bind(this)}
            //ifShake={ifShake}
            />
          </div>
        </div>
        {/* <MenuList menuClick={this.menuClick} activeMenu={activeMenu}/>  */}
        <Switch>
          {menuList.map((v, i) => <Route key={i} path={`/mainPage/${v.name}`} render={() => <v.component />} />)}

        </Switch>
      </div>)
}}

我們直接在layout里面定義了我們需要的路由,V4方便的地方就是我們可以將路由寫(xiě)在一個(gè)文件里面隨意的配置改動(dòng),非常的方便。
總結(jié)一下,雖然React Router v4 重構(gòu)了路由使用的思想,但卻和React的設(shè)計(jì)思想更加切合,個(gè)人認(rèn)為是一個(gè)巨大的進(jìn)步。使用React Router v4 時(shí),你需要忘掉以前使用靜態(tài)路由的思維方式,把路由當(dāng)成普通組件看待,習(xí)慣了這個(gè)思維轉(zhuǎn)變后,你就會(huì)發(fā)現(xiàn)React Router v4的魅力所在了。

參考博客連接:http://m.itdecent.cn/p/30b6ebe82a07

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 react-router針對(duì)不同的使用場(chǎng)景衍生了不同的路由包,RN項(xiàng)目用react-router-nativ...
    大柚子08閱讀 36,721評(píng)論 5 39
  • React Router v4 發(fā)布已經(jīng)有幾個(gè)月了,但好像并沒(méi)有得到太多人的青睞,大家(包括我們團(tuán)隊(duì)自己)還是習(xí)慣...
    艾特老干部閱讀 3,677評(píng)論 5 15
  • 大部分人都說(shuō)孩子很天真,什么都不懂,其實(shí)孩子不是不懂只是不想懂或者說(shuō)裝作不懂,大人的一時(shí)生氣打罵了孩子,總...
    四月_52b6閱讀 268評(píng)論 0 0
  • 職場(chǎng)不需要彰顯個(gè)性 ,要么合群,要么出局! 很多時(shí)候,職場(chǎng)很殘酷,因?yàn)槁殘?chǎng)沒(méi)有完美的個(gè)人,只有完美的團(tuán)隊(duì)。 兩個(gè)...
    莎朵閱讀 716評(píng)論 0 4
  • 每個(gè)人生路上的岔口, 徘徊著我選擇的憂愁: 左邊高山水流, 右邊浪里泛舟。 不畏山高水遠(yuǎn), 但求心堅(jiān)槳款。 我有平...
    范高閱讀 357評(píng)論 0 0

友情鏈接更多精彩內(nèi)容