React路由

react-router React路由哩盲,讓父組件動(dòng)態(tài)去掛載不同的子組件沿后,本文以4.x為例闷游;
4.x 對(duì)依賴包的劃分:

  • react-router 路由基礎(chǔ)庫(kù)
  • react-router-dom 適用于瀏覽器環(huán)境的再次封裝
  • react-router-native 適用于原生開發(fā)環(huán)境的再次封裝
  • react-router-config 靜態(tài)路由配置助手

v4v5用法差不多惊奇,但與v2/v3差異較大,v4/v5采用的是動(dòng)態(tài)路由开仰,而v2/v3采用的是靜態(tài)路由拟枚。
v5 新增了一些新特性薪铜,向后兼容:

  • 消除了嚴(yán)格模式的警告
  • 對(duì)react v16有了更好的支持
  • 升級(jí)了react context api
  • 預(yù)優(yōu)化build,無(wú)需考慮生產(chǎn)環(huán)境和開發(fā)環(huán)境

react-router 主張 一切皆組件梨州,不像vue-router那樣做中心化配置(集中式路由)痕囱。當(dāng)然眶根,react也支持集中式路由呛牲。

  • 前端路由的實(shí)現(xiàn):history庫(kù),管理瀏覽器會(huì)話歷史的工具庫(kù)沼瘫。本質(zhì)上還是包裝了原生BOM中的 window.historywindow.location.hash
  • 核心組件:<BrowserRouter>每窖、<HashRouter>帮掉、<Route>、<Redirect>窒典、<Link>蟆炊、<NavLink>、<Switch>
    • Hash模式:<HashRouter>
    • HTML5:history模式:<BrowserRouter>
    • react native開發(fā)使用的是 MemoryHistory
  • 對(duì)象:history瀑志、match涩搓、withRouter

引入路由之后,可以把組件分為兩類:普通組件(components目錄)劈猪、路由組件(views目錄)

基本配置

  1. 安裝react-router-dom模塊:npm install react-router-dom -S
  2. 在根組件App.js中引入路由相關(guān)的組件昧甘,加載的子組件包括Home.js、News.js战得、Product.js充边、NotFound.js
    import { BrowserRouter, Route, NavLink, Switch } from 'react-router-dom'
    render() {
        return(<BrowserRouter>
            <div>
                <header>
                    <NavLink to="/">首頁(yè)</NavLink>
                    <NavLink to="/news">新聞</NavLink>
                    <NavLink to="/product">商品</NavLink>
                    <NavLink to="/notfound">一個(gè)不存在的路由</NavLink>
                </header>
                <Switch>
                    <Route exact path="/" component={Home} />
                    <Route path="/news" component={News} />
                    <Route path="/product" component={Product} />
                    <Route component={NotFound} />  // 404組件
                </Switch>
            </div>
        </BrowserRouter>)
    }
    
    • 在根組件中,把Home組件的路由配置為path="/"常侦,表示默認(rèn)加載Home組件浇冰;
    • exact:表示嚴(yán)格匹配模式,必須完全匹配聋亡,如果設(shè)置為false肘习,每次都會(huì)匹配 path="/" 的路由;
    • 404組件不需要聲明任何path坡倔,且必須放在最后面漂佩,當(dāng)上面的所有路由都沒(méi)有匹配時(shí),則匹配404路由致讥。
  3. Redirect 表示重定向仅仆,可用于指定默認(rèn)路由
    import { BrowserRouter, Route, NavLink, Switch, Redirect } from 'react-router-dom'
    render() {
        return(<BrowserRouter>
            <div>
                <header>
                    <NavLink to="/">首頁(yè)</NavLink>
                    <NavLink to="/news">新聞</NavLink>
                    <NavLink to="/product">商品</NavLink>
                </header>
                <Switch>
                    <Route path="/home" component={Home} />
                    <Route path="/news" component={News} />
                    <Route path="/product" component={Product} />
                    <Redirect to="/home" />  //默認(rèn)路由器赞,加載Home組件
                </Switch>
            </div>
        </BrowserRouter>)
    }
    
  4. 一個(gè)項(xiàng)目中只有一個(gè)<BrowserRouter>垢袱,所以 <BrowserRouter> 包裹根組件即可!
  5. <NavLink><Route>必須包裹在<BrowserRouter>中港柜,且<BrowserRouter>只能有一個(gè)直接子節(jié)點(diǎn)请契;
  6. NavLinkLink:它們最終都被解析為HTML中的<a>咳榜,但內(nèi)部會(huì)阻止瀏覽器的默認(rèn)行為;
    • to 屬性用于指定跳轉(zhuǎn)的路由爽锥,也可以是一個(gè)對(duì)象
      <Link to={{ pathname: '/courses', search: '?sort=name', hash: '#the-hash', state: { fromDashboard: true } }}/>
      
    • <NavLink><Link>的一個(gè)特定版本涌韩,它會(huì)在匹配上當(dāng)前的url時(shí)給已經(jīng)渲染的元素添加參數(shù);
    • <NavLink> 上的屬性:activeClassName氯夷、activeStyle臣樱、exact、strict ...
      <NavLink className="normal" activeClassName="active" to="/news">
      //NavLink的默認(rèn)樣式className=""腮考,匹配時(shí)的激活樣式:activeClassName="" 或 activeStyle={}
      
    • 自定義NavLinkMyNavLink.jsx雇毫,統(tǒng)一使用一個(gè)activeClassName
      import React, {Component} from 'react'
      import {NavLink} from 'react-router-dom'
      export default class MyNavLink extends Component {
          render() {
              return <NavLink {...this.props} activeClassName='active'>
          }
      }
      
  7. Routepath指定路由,component指定路由對(duì)應(yīng)的組件踩蔚;
  8. Switch:從上往下匹配時(shí)棚放,只要匹配成功,就不會(huì)再向下匹配馅闽,即只顯示與當(dāng)前路由匹配的Route飘蚯;
  9. <NavLink><Route>可以不在同一個(gè)組件中,只要路由匹配福也,都可以實(shí)現(xiàn)路由跳轉(zhuǎn)局骤。

路由傳值

  1. 動(dòng)態(tài)路由傳參:<Route path="/info/:id" component={Info} />
    this.state = { id:12 }
    
    1. :id 表示占位符,對(duì)應(yīng)的NavLink
      <NavLink to={`/info/${this.state.id}`}>詳情</NavLink>
      
    2. Info.js 組件中獲取動(dòng)態(tài)路由的參數(shù)idthis.props.match.params
      componentDidMount() {
          let { id } = this.props.match.params
      }
      
  2. GET方式傳參
     <Route path="/info" component={Info} />
     <NavLink to={`/info?id=${this.state.id}`}>詳情</NavLink>
    
    1. Info.js 組件中拟杉,獲取參數(shù)的對(duì)象:this.props.location
       const { search } = this.props.location
      
    2. 但是庄涡,GET參數(shù)并沒(méi)有被解析,仍是一個(gè)原始字符串:?id=12
    3. 借助第三方模塊url解析get參數(shù):npm install url --save
      import url from 'url'  //url模塊是node上的內(nèi)置模塊搬设,npm上的url模塊并不是node的
      componentDidMount() {
          let { id } = url.parse(this.props.location.search, true).query
      }
      
    4. React不建議使用 ?xxx=xxx的方式傳參穴店,而是把 to 設(shè)置為對(duì)象
      <NavLink to={ { pathname:'/info', id:this.state.id } }>詳情</NavLink>
      
  3. React解析原始HTML字符串:dangerouslySetInnerHTML屬性
    this.state = { content: '<p>原始HTML字符串</p>' }
    <div dangerouslySetInnerHTML={{__html: this.state.content}}></div>
    

路由嵌套

  1. User.js 組件是根路由 App.js 的動(dòng)態(tài)子組件,路由名稱為/user
    1. User組件中再配置兩個(gè)動(dòng)態(tài)子組件:Main.jsInfo.js
      import { Route, NavLink, Redirect, Switch } from 'react-router-dom'
      render() {
          return(<div>
              <div className="left">
                  <NavLink to="/user/">個(gè)人中心</NavLink>
                  <NavLink to="/user/info">用戶詳情</NavLink>
              </div>
              <div className="right">
                  <Switch>
                      <Route exact path="/user/" component={Main} />
                      <Route path="/user/info" component={Info} />
                  <Switch>
              </div>
          </div>)
      }
      
    2. User組件的路由為/user拿穴,則把子組件Main的路由設(shè)置為/user/泣洞,表示默認(rèn)加載Main組件;
    3. 亦或者,Redirect 重定向的方式實(shí)現(xiàn)默認(rèn)加載的路由組件
      render() {
          return(<div>
              <div className="left">
                  <NavLink to="/user/center">個(gè)人中心</NavLink>
                  <NavLink to="/user/info">用戶詳情</NavLink>
              </div>
              <div className="right">
                  <Switch>
                      <Route exact path="/user/center" component={Main} />
                      <Route path="/user/info" component={Info} />
                      <Redirect to='/user/center' />
                  <Switch>
              </div>
          </div>)
      }
      
    4. Redirectto 屬性也可以是一個(gè)對(duì)象:pathname表示路由地址默色,其他的是參數(shù)球凰;
      <Redirect to={ {pathname:'/', state:{foo:'bar'}} } />
      
  2. 動(dòng)態(tài)獲取父級(jí)的路由,再拼接成自己組件的路由
    <Route exact path={`${this.props.match.url}/`} component={Main} />
    <Route path={`${this.props.match.url}/info`} component={Info} />
    

JS控制路由跳轉(zhuǎn)

  1. 借助對(duì)象:this.props.history 中的方法
  2. push()腿宰、replace()呕诉、goBack()、goForward() ......
    this.props.history.push('/home/user');
    this.props.history.push({ pathname: '/home/user', state: { foo:'bar' } });
    
  3. 獲取傳遞的參數(shù):this.props.location
    const { foo } = this.props.location.state;
    

路由守衛(wèi)

  1. 路由守衛(wèi)其實(shí)就是路由攔截吃度,可以做權(quán)限控制甩挫,它其實(shí)也是一個(gè)組件,返回值是一個(gè)Route組件椿每;
    class RouteGuard extends Component {
        state = {
            isLogin: false
        }
        render() {
            const {component:Component, ...otherProps} = this.props
            return (
                <Route {...otherProps} render={props => (
                    //只有已經(jīng)登錄了才允許進(jìn)入守衛(wèi)路由對(duì)應(yīng)的組件伊者,沒(méi)有登錄則重定向到登錄頁(yè)
                    this.state.isLogin ? <Component {...props}></Component> : 
                    (<Redirect to={{ pathname:'/login', state:{from:props.location.pathname} }} />)
                )}></Route>
            )
        }
    }
  1. 在需要控制權(quán)限的地方英遭,應(yīng)用路由守衛(wèi)
    render() {
        return(<BrowserRouter>
            <div>
                <header>
                    <NavLink to="/">首頁(yè)</NavLink>
                    <NavLink to="/news">新聞</NavLink>
                    <NavLink to="/mine">我的</NavLink>
                </header>
                <Switch>
                    <Route exact path="/" component={Home} />
                    <Route path="/news" component={News} />
                    <RouteGuard path="/mine" component={Mine} />  // 應(yīng)用路由守衛(wèi)
                </Switch>
            </div>
        </BrowserRouter>)
    }

路由的模塊化

  1. 用一個(gè)數(shù)組管理項(xiàng)目中的所有路由,在把這個(gè)數(shù)組放在一個(gè)獨(dú)立的JS文件中
    1. router.js 中引入相關(guān)組件亦渗,管理路由
      const routes = [
          { path:'/', component:Home, exact:true },
          { path:'/user', component:User }
      ]
      export default routes;
      
    2. 在根組件App中引入路由模塊
      import routes from './route/router.js'
      render(){
          return(<BrowserRouter>
              <header>
                  <NavLink to="/">首頁(yè)</NavLink>
                  <NavLink to="/user">用戶</NavLink>
              </header>
              {
                  routes.map((route, key) => {
                      if(route.exact) {
                          return <Route key={key} exact path={route.path} component={route.component} />
                      } else {
                          return <Route key={key} path={route.path} component={route.component} />
                      }
                  })
              }
          </BrowserRouter>)
      }
      
  2. 嵌套路由的管理
    1. router.js
      const routes = [
          { path:'/', component:Home, exact:true },
          { path:'/user', component:User,
              routes:[
                  { path:'/user/', component:Main }, 
                  { path:'/user/info', component:Info }
              ]
          }
      ]
      
    2. 在根組件App中挖诸,通過(guò)<Route>render 屬性,把子路由傳遞給子組件
      <Route key={key} path={route.path} render={props => (
          <route.component {...props} routes={route.routes} />
      )} />
      
    3. User組件中獲取子路由:this.props.routes
      render() {
          return(<div>
              <div className="left">
                  <NavLink to="/user/">個(gè)人中心</NavLink>
                  <NavLink to="/user/info">用戶詳情</NavLink>
              </div>
              <div className="right">
                  {
                      this.props.routes.map((route, key) => {
                          return <Route key={key} exact path={route.path} component={route.component} />
                      })
                  }
              </div>
          </div>)
      }
      
  3. 子路由的<Route />上可以都加上 exact 屬性法精,而根路由的<Route />上不行多律!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市搂蜓,隨后出現(xiàn)的幾起案子菱涤,更是在濱河造成了極大的恐慌,老刑警劉巖洛勉,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粘秆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡收毫,警方通過(guò)查閱死者的電腦和手機(jī)攻走,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)此再,“玉大人昔搂,你說(shuō)我怎么就攤上這事∈淠矗” “怎么了摘符?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)策吠。 經(jīng)常有香客問(wèn)我逛裤,道長(zhǎng),這世上最難降的妖魔是什么猴抹? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任带族,我火速辦了婚禮,結(jié)果婚禮上蟀给,老公的妹妹穿的比我還像新娘蝙砌。我一直安慰自己,他們只是感情好跋理,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布择克。 她就那樣靜靜地躺著,像睡著了一般前普。 火紅的嫁衣襯著肌膚如雪肚邢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天汁政,我揣著相機(jī)與錄音道偷,去河邊找鬼。 笑死记劈,一個(gè)胖子當(dāng)著我的面吹牛勺鸦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播目木,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼换途,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了刽射?” 一聲冷哼從身側(cè)響起军拟,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎誓禁,沒(méi)想到半個(gè)月后懈息,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摹恰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年辫继,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俗慈。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姑宽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出闺阱,到底是詐尸還是另有隱情炮车,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布酣溃,位于F島的核電站瘦穆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赊豌。R本人自食惡果不足惜难审,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望亿絮。 院中可真熱鬧告喊,春花似錦、人聲如沸派昧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蒂萎。三九已至秆吵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間五慈,已是汗流浹背纳寂。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工主穗, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毙芜。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓忽媒,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親腋粥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子晦雨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 簡(jiǎn)介:簡(jiǎn)單實(shí)現(xiàn)react-redux基礎(chǔ)api react-redux api回顧 把store放在context...
    Rainie_1fb7閱讀 744評(píng)論 0 1
  • state state是指組件的當(dāng)前狀態(tài)。組件根據(jù)狀態(tài)state呈現(xiàn)不同的UI展示隘冲。 一旦狀態(tài)(數(shù)據(jù))更改闹瞧,組件就...
    Galette_LJ閱讀 1,475評(píng)論 0 0
  • 本文主要談自己在react學(xué)習(xí)的過(guò)程中總結(jié)出來(lái)的一些經(jīng)驗(yàn)和資源,內(nèi)容邏輯參考了“深入react技術(shù)椪勾牵”一書以及網(wǎng)上...
    AirCloud閱讀 863評(píng)論 0 1
  • 思考一個(gè)問(wèn)題:在DOM結(jié)構(gòu)中的某一個(gè)div元素奥邮,是一個(gè)對(duì)象嗎? 如果第一時(shí)間無(wú)法確定的同學(xué)可以在瀏覽器的Conso...
    這波能反殺閱讀 3,622評(píng)論 10 49
  • React組件 React的組件大概分為倆部分罗珍,無(wú)狀態(tài)組件和有狀態(tài)組件 無(wú)狀態(tài)組件漠烧。下面React官網(wǎng)中定義的一個(gè)...
    lijinfei閱讀 315評(píng)論 0 0